阅读《你不知道JS:这个和对象原型》一书时
我找到了这个关于this
绑定的例子:
function foo(something) {
this.a = something;
}
var obj1 = {
foo: foo
};
var obj2 = {};
obj1.foo( 2 );
console.log( obj1.a ); // 2
obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3
var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4
我不明白为什么在执行新的obj1.foo(4)后,console.log(obj1.a)
打印2
而不是4
。如果我评论该行obj1.foo(2)
上面日志的结果是undefined
.
因为任何函数都可以是构造函数。想象一下,如果您单独使用foo
:
var obj3 = new foo(3);
你也希望得到一个类似的对象{ a: 3 }
,对吧?
即使函数附加到其他内容,这仍然有效。每次使用 new
时,您都会创建一个新对象,而不是更改现有对象。
首先,您将函数用作方法:
obj1.foo(2);
在这种情况下,上下文设置为 obj1
,因为它是调用它的上下文。但是,当您使用new
时,将创建一个全新的对象,并将该新对象用作上下文。
当你调用这个obj1.foo( 2 )
你执行obj1
传递作为参数传递 2 的方法。当执行foo
时,为调用对象定义一个名为 a
的属性,并为其分配值 something
, 在本例中为 2。在这种情况下,calling
对象是 obj1
。因此,出于这个原因,obj1
获得了一个名为 a
的财产,价值为 2。
如果我评论这一行:obj1.foo(2),上面日志的结果是 定义。
发生这种情况是因为如果您评论您提到的行。obj1
不会获得财产a
。因此,在这种情况下a
是未定义的。一般来说,如果我们考虑一个空对象obj
,obj = {}
.如果执行以下操作:
obj.a
在对象obj
上定义一个名为 a
的属性。此外,如果您执行以下操作:
obj.a = 4;
你做两件事,你定义属性a
并给它赋值。
因此,让我们将其分解为更小的步骤。
首先,obj1.foo
调用foo
函数。foo
函数接受一个参数,并将该参数分配给调用foo的对象的a
键(它比这要复杂一些,如果您愿意,我可以在之后详细说明)。
因此,当您调用 obj1.foo(2)
时,您正在调用 foo
方法,传入由obj1
对象的透视2
的参数。这就是为什么obj1.a
等于 2。由于这是为obj1.a
赋值的命令,省略该调用将导致obj1.a
未定义。