2. Every function is an object
在JavaScript中每个函数都是对象。
(说了等于没说)怎么理解这句话?
敲在编辑器中的代码只是代码,被js引擎导入以后的代码中
的每个函数定义就成为了对象。
或者说就被js engine表示成了对象,更进一步说是
Function的实例。
这些函数对象和其他对象一样也包含了你能访问的属性,比
如name, length, prototype。也包括了你不能通过代码访
问的内部属性。其中一个属性就是[[Scope]],在ECMA-262,
Third Edition中定义。
3. 创建函数对象时生成作用域链
function add(num1, num2) {
var sum = num1 + num2;
return sum;
}
When the function is created, its scope chain is populated
with global object 这个集合就被称为函
这个集合由变量对象
[[Scope]]属性指向一 variable object组
数的作用域链
个集合 成。
作用域链就决定了函数可以
js engine读到函数定义,创
访问到的数据。
建函数对象,生成作用域
这个全局变量对象由一些键值
链。
对组成key-value pairs
4. 执行函数时
var total = add(5, 10);
执行add函数时,js engine就会为该函数创建一个内部对
象--执行上下文execution context。同一个函数每次执行
时都会创建一个EC,这个EC定义了函数在这次执行时的环
境,所以称它为执行上下文。当函数执行完以后,该EC就会
被销毁,它所占内存就被释放。
6. 理解闭包:内嵌函数nested function
var scope = "global"; // 全局变量scope
function checkscope() {
var scope = "local"; // 局部变量scope
function f() { return scope; } // 返回变量scope的值
return f; // 返回内嵌函数
}
var f = checkscope(); // 变量 f 指向内嵌函数实
例
f();
7. var f = checkscope();
函数checkscope执行,返回内嵌函数,该内嵌函数也是一个
对象(记得吗?everything is object),更具体的说是一
个函数实例对象。这个对象也有Scope属性,指向scope
chain,而且这个SC的variable object就是checkscope函数
的变量对象,js的设计很神奇!这样做很有趣,但带来了副
作用。
9. var uniqueInteger = (function() { // Define and invoke
var counter = 0; // Private state of function below
return function() { return counter++; };
}());
uniqueInteger(); // ==> 0
uniqueInteger(); // ==> 1
10. function counter() {
var n = 0;
return {
count: function() { return n++; },
reset: function() { n = 0; }
};
}
var c = counter(), d = counter(); // Create two counters
c.count() // => 0
d.count() // => 0: they count independently
c.reset() // reset() and count() methods share state
c.count() // => 0: because we reset c
d.count() // => 1: d was not reset
11. function addPrivateProperty(o, name, predicate) {
var value; // This is the property value
// The getter method simply returns the value.
o["get" + name] = function() { return value; };
// The setter method stores the value or throws an exception if
// the predicate rejects the value.
o["set" + name] = function(v) {
if (predicate && !predicate(v))
throw Error("set" + name + ": invalid value " + v);
else
value = v;
};
}
var o = {}; // Here is an empty object
addPrivateProperty(o, "Name", function(x) { return typeof x == "string"; });
o.setName("Frank"); // Set the property value
console.log(o.getName()); // Get the property value
o.setName(0); // Try to set a value of the wrong type
12. function constfunc(v) { return function() { return v; }; }
var funcs = [];
for(var i = 0; i < 10; i++) funcs[i] = constfunc(i);
funcs[5]() // => 5
13. function constfuncs() {
var funcs = [];
for(var i = 0; i < 10; i++)
funcs[i] = function() { return i; };
return funcs;
}
var funcs =
constfuncs();
funcs[5]();
14. Another thing to remember when writing closures is that this is a JavaScript
keyword,not a variable. As discussed earlier, every function invocation has a
this value, and a closure cannot access the this value of its outer function
unless the outer function has saved that value into a variable:
var self = this; // Save this value in a variable for use by nested funcs.
The arguments binding is similar. This is not a language keyword, but it is
automatically declared for every function invocation. Since a closure has
its own binding for arguments, it cannot access the outer function’s
arguments array unless the outer func-tion has saved that array into a variable
by a different name:
var outerArguments = arguments; // Save for use by nested functions