关于JavaScript的执行域,标识符解析,闭包的研究 Published on 28 July 2008 by laruence 本文地址: https://www.laruence.com/2008/07/28/210.html 转载请注明出处 本文有些纰漏, 请以:Javascript作用域原理为准. 谢谢. 如果之前的纰漏给大家造成了误解, 请原谅. 谢谢. Filed in Js/CSS, 随笔 javascript Previous Post Apache启动过程(PHP_MINIT_FUNCTION的调用) Next Post 揭秘TSRM(Introspecting TSRM)
LungZeno May 10, 2009 現在想一想,其實你也對,更正確地說,specification寫的 scope chain 實際上是串列(list)結構、堆疊介面。 這就是 Javascript 與 C/C++ 和 Java 不同的地方,在一個物件的方法內使用該物件的任何屬性也須明確地透過 this 等物件參考該些屬性,並沒有 instance scope ,除非使用 with statement 來模擬。 apply 和 call 做的是由它們把自己的第一個參數作為 this 值提供給原方法的 [[Call]]。
LungZeno May 11, 2009 再補充,你也非錯, specification 是沒有寫任何關於資源回收(垃圾收集)的事的,因此某良好實現的可能情況如下: 當 class 函式執行完畢返回後,那次執行 class 時產生的活性物件在返回後的 context 已變得不可達了,因而保證那活性物件儲存的屬性鍵例如 private 鍵不會再被參考,那麼,那活性物件和它儲存的屬性鍵例如 private 鍵可以被回收,當 private 鍵被回收後, private 值如果變得不可達,則也可被回收。 看你對 php 的探究後得到的啟發,屬性鍵和屬性值應該分開考慮。
LungZeno May 10, 2009 我想,你是有點弄錯了。 Javascript 的 scopes 依然是堆疊(stack)機制的,全部 lexical scopes 本身就是構成單根的樹(如果不計較 with 語句的話),函式的[[Scope]]屬性儲存的是該函式在宣告或定義時的 scope chain ,並不因呼叫而改變(如果因呼叫而改變的話,則(直接或間接)遞迴呼叫怎麼算?),最新的 specification 寫得更清楚,依你的用語,你的第一個例子應該是這樣: b的[[scope]]:全局活动对象; 调用b()的时候:b的该次活动对象->全局活动对象; a的[[scope]]:全局活动对象; 调用a()的时候:a的该次活动对象->全局活动对象; 你的第二個例子應該是這樣: a的[[scope]]:a定義时b的活动对象->全局活动对象; 调用a()的时候:a的该次活动对象->a定義时b的活动对象->全局活动对象; 閉包一詞的名字實在無法完整涵蓋 closure 的意思,程式語言用語中的 closure 本身就直接來自數學(因為本來是函數式程式語言的東西,所以我這麼肯定),很多時是指由某運算或某關係滿足某種性質而產生的對各元素都有定義的最小集合,閉包一詞的字面意思只表達了對各元素都有定義即閉合集合這層意思,而欠了最小集合這層意思。 Javascript 暫時都還沒有存取權限控制的能力,只能近似地模擬,但始終可視性不等於可存取性。 因為那個名叫 private 的變數不再被參考,所以活性物件(activation object)才被回收。 new 一個物件時,和呼叫函式有分別, this 的值是由 [[Construct]] 提供給 [[Call]] , specification 那處指的 caller 此時是指 [[Construct]] ,並不是指 objRef 。 其實 Javascript 用語 caller 指的是被呼叫的函式在被呼叫處的 scope 所屬的函式,例如 function a(){ b(); } // a 就是 b 的 caller 又是不好的翻譯,public 是「公開」,原型物件的屬性是共享的,直接修改原型物件的屬性會影響到所有繼承該原型的實體(instance),只不過在 Javascript 中,對一個物件寫 inherited property (取存子屬性(accessor property)除外)會在該物件上創建 own property 。 其實「对象」也是不好的翻譯,甚麼有人得出「受词」這樣的翻譯,這都是對 object 一字在電腦程式語言中的用法缺乏了解和缺乏不同角度思考所致。
eason August 28, 2008 function makefunc(x){ return x; } var am=[makefunc(0),makefunc(1),makefunc(2) ] 请问这段代码创建了几个活动对象(调用对象)?我的想法是,如果活动对象是不是在函数每次调用的时候都创建?还是在函数定义的时候创建一个,以后就不创建了?
現在想一想,其實你也對,更正確地說,specification寫的 scope chain 實際上是串列(list)結構、堆疊介面。
這就是 Javascript 與 C/C++ 和 Java 不同的地方,在一個物件的方法內使用該物件的任何屬性也須明確地透過 this 等物件參考該些屬性,並沒有 instance scope ,除非使用 with statement 來模擬。
apply 和 call 做的是由它們把自己的第一個參數作為 this 值提供給原方法的 [[Call]]。
再補充,你也非錯, specification 是沒有寫任何關於資源回收(垃圾收集)的事的,因此某良好實現的可能情況如下:
當 class 函式執行完畢返回後,那次執行 class 時產生的活性物件在返回後的 context 已變得不可達了,因而保證那活性物件儲存的屬性鍵例如 private 鍵不會再被參考,那麼,那活性物件和它儲存的屬性鍵例如 private 鍵可以被回收,當 private 鍵被回收後, private 值如果變得不可達,則也可被回收。
看你對 php 的探究後得到的啟發,屬性鍵和屬性值應該分開考慮。
我想,你是有點弄錯了。
Javascript 的 scopes 依然是堆疊(stack)機制的,全部 lexical scopes 本身就是構成單根的樹(如果不計較 with 語句的話),函式的[[Scope]]屬性儲存的是該函式在宣告或定義時的 scope chain ,並不因呼叫而改變(如果因呼叫而改變的話,則(直接或間接)遞迴呼叫怎麼算?),最新的 specification 寫得更清楚,依你的用語,你的第一個例子應該是這樣:
b的[[scope]]:全局活动对象;
调用b()的时候:b的该次活动对象->全局活动对象;
a的[[scope]]:全局活动对象;
调用a()的时候:a的该次活动对象->全局活动对象;
你的第二個例子應該是這樣:
a的[[scope]]:a定義时b的活动对象->全局活动对象;
调用a()的时候:a的该次活动对象->a定義时b的活动对象->全局活动对象;
閉包一詞的名字實在無法完整涵蓋 closure 的意思,程式語言用語中的 closure 本身就直接來自數學(因為本來是函數式程式語言的東西,所以我這麼肯定),很多時是指由某運算或某關係滿足某種性質而產生的對各元素都有定義的最小集合,閉包一詞的字面意思只表達了對各元素都有定義即閉合集合這層意思,而欠了最小集合這層意思。
Javascript 暫時都還沒有存取權限控制的能力,只能近似地模擬,但始終可視性不等於可存取性。
因為那個名叫 private 的變數不再被參考,所以活性物件(activation object)才被回收。
new 一個物件時,和呼叫函式有分別, this 的值是由 [[Construct]] 提供給 [[Call]] , specification 那處指的 caller 此時是指 [[Construct]] ,並不是指 objRef 。
其實 Javascript 用語 caller 指的是被呼叫的函式在被呼叫處的 scope 所屬的函式,例如
function a(){ b(); } // a 就是 b 的 caller
又是不好的翻譯,public 是「公開」,原型物件的屬性是共享的,直接修改原型物件的屬性會影響到所有繼承該原型的實體(instance),只不過在 Javascript 中,對一個物件寫 inherited property (取存子屬性(accessor property)除外)會在該物件上創建 own property 。
其實「对象」也是不好的翻譯,甚麼有人得出「受词」這樣的翻譯,這都是對 object 一字在電腦程式語言中的用法缺乏了解和缺乏不同角度思考所致。
受教了, 这个是我之前的一个总结, 也许有用词不对的地方.
但是apply和call的时候, 不就是将此时的this对象附加到scope chain上么?
You write very well.
在调用的时候创建.
function makefunc(x){
return x;
}
var am=[makefunc(0),makefunc(1),makefunc(2) ]
请问这段代码创建了几个活动对象(调用对象)?我的想法是,如果活动对象是不是在函数每次调用的时候都创建?还是在函数定义的时候创建一个,以后就不创建了?