在前面的文章中我們提到過變數物件(variable object),我們在js**中申明的所有變數都儲存在變數物件當中,除此之外變數物件中還可能包含以下內容。
(1)函式的引數(arguments,es6中廢棄)。
(2)當前執行上下文的所有函式申明(通過function申明的函式)。
(3)當前上下文的所有變數申明(通過var申明的變數)。
一,建立過程
變數物件的建立依次經歷了一下過程
1,在chrome瀏覽器中,變數物件會首先獲得函式的引數及其值,在firefox瀏覽器中,是直接將引數物件arguments儲存在變數物件中。
2,依次獲取當前執行上下文的所有函式申明,也就是function申明的函式,在變數物件中會以函式名建立乙個與之相對應的屬性,屬性值為指向所在記憶體位址的引用,如果函式名的屬性已經存在,那麼屬性的值會被新的引用覆蓋。
3,依次獲取當前執行上下文的所有變數申明,也就是使用var關鍵字申明的變數。每找到乙個申明就在變數物件當中以變數名建立乙個屬性,屬性值為undefined,如果該變數的屬性已經存在,為了防止同名函式被修改為undefined,則會直接跳過去,原屬性值不會被修改
es6支援新的變數申明方式,規則與var完全不同,他們是在上下文執行階段開始執行的,避免了變數提公升帶來的一系列問題。
我們知道了上面的規則之後,我們思考乙個問題,當我們執行上下文**的時候具體的執行過程是怎麼樣的呢?
var a=20;
首先上下文階段會先確認變數物件,而變數物件的建立過程則是先獲取變數名並賦值為undefined,因此第一步是:
var a = undefined;
上下文的建立階段完畢後,開始進入執行階段,在執行階段需要完成變數的賦值工作,因此第二步是:
a =30;
需要注意的是,這兩步分別是在上下文的建立階段與執行階段完成的因此var a=undefined這一步其實提前到了比較早的地方取執行,下面通過乙個簡單的列子來證明。
console.log(a);//這個時候的a輸出的結果為undefined。
var a = 30;
結合之前的解釋,這個列子的實際執行順序為
//c建立階段
var a = undefined;
//執行階段
console.log(a);
a=30;
這種現象被稱為變數提公升(hoisting).
從上面的例子我們可以看出,在變數物件建立的過程當中,函式申明的執行優先順序會比變數的優先順序高一些,而且同名的函式會覆蓋函式與變數,同名的變數不會覆蓋函式。但在上下文的執行階段,同名函式會被變數重新賦值。
var a=20;
function fn();
function fn();
function fn();
consle.log(a);
fn();
var fn = 'i vant conver function named fn';
console.log(fn);
//20;
//conver a
//i vant conver function named fn
上面**的執行順序為
//建立階段
function fn();
function fn();
function fn();
var a =undefined;
var fn=undefined;
//執行階段
a=20;
consle.log(a);
fn();
fn='i vant conver function named fn';
consle.log(fn);
根據輸出結果可以證明,在建立階段,後建立的函式會覆蓋前面建立的函式,但是後建立的變數fn並沒有覆蓋前面建立的函式fn。而在執行階段,a與fn的重新賦值導致他們發生了變化。
二,實列分析
為了更加深刻的理解變數物件,下面結合一些簡單的列子來進行**。
//demo1
function test(),//變數物件
scopechain:,//作用域鏈
this:{}
//這裡我們暫時不分析作用域鏈與this,後續章節會詳細講解
//vo為variable object的縮寫,既變數物件
vo=,
foo:,
a:undefined
在函式呼叫棧中,如果當前執行函式處於棧頂,則意味著當前執行上下文處於啟用狀態,此時變數物件稱之為活動物件(ao,activation object)。活動物件包含變數物件的所有屬性,並且此時所有的屬性已經完成了賦值,除此之外,活動物件還包含了this指向。
//執行階段
vo->ao
ao=,
foo:,
a:1,
this:window
我們可以通過斷點除錯的方式在chrome開發者工具中檢視這一過程。
因此上面**的實際實現順序為
function test(),
this:window,
除此之外,全域性上下文的生命週期與程式的生命週期一樣,只要程式執行不結束。全域性上下文就會一直存在,其他的上下文環境都能直接訪問到全域性上下文的屬性。
下一章我們講講作用域與作用域鏈
JS系列 物件詳解
1.1 萬物皆物件 一 竟 1.1.1 都是物件 1.1.2 也有例外typeof true boolean typeof 123 number typeof str string typeof undefined undefined typeof null object 複製 1.1.3 結論 1...
js 物件 函式 變數
物件組成 屬性 常用名詞 方法 常用動詞 函式 把一段可以重複的 封裝,讓大量 可以重複使用 用函式的方法求1到100的和 function getsum num1,num2 var sum 0 for var i num1 i num2 i sum sum i console.log sum ge...
js物件和變數
var person 物件屬性有兩種定址方式 name person.lastname name person lastname 訪問物件方法 返回函式執行結果 person.fullname john doe訪問 person 物件的 fullname 屬性 返回函式表示式 person.full...