有两种方法可以让对象方法引用对象属性:
let i = {a: 'apple', b: function(){return i.a}}
let j = {a: 'apple', b: function(){return this.a}}
console.log(i.b()) // apple
console.log(j.b()) // apple
引用对象属性的这两种方法的优缺点是什么??
它们的含义不同。第一个返回作用域中某个变量i
的a
属性。该对象也被命名为i
,这意味着它可以按预期工作。但这并不能保证。例如:
let i = {a: 'apple', b: function(){return i.a}}
let j = i
i = {a: "potato"}
console.log(j.b()) // apple or potato?
只要您期望函数查看范围,找到一个i
并返回它的a
道具,那么这就可以按预期工作。但这并不意味着,在这个函数中返回对象的a
属性。
第二个是否意味着,只要它是用i.b()
调用的,但this
并不指定义函数的对象——它的值由函数调用的上下文决定。例如
let i = {a: 'apple', b: function(){return this.a}}
let j = {a: 'potato'}
j.b = i.b
console.log(j.b()) // apple or potato
一个并不比另一个更好,它们是不同的想法,可以发挥不同的功能。
实际上,这些函数并不是在做同样的事情。
让我们考虑第一个。
let i = {a: 'apple', b: function(){return i.a}}
您定义了一个函数function(){return i.a}
,它将从对象i返回一个值。无论何时何地调用它,它都将返回对象i的值。它完全独立于范围。不能将此函数作为原型的方法重用。因为i
总是i
。如果您没有使用箭头函数来保护您的呼叫上下文,那么它可能会很有用。
另一方面,其他功能是不同的。
let j = {a: 'apple', b: function(){return this.a}}
您正在使用this
,因此它将根据其上下文访问属性a。
通过一个例子让一切变得更加清晰。假设我有一个属性为sound
的绵羊和狗对象。
const dog = {
sound: 'woof-woof'
};
const sheep = {
sound: 'Meaeeeeee'
};
现在我正在定义一个函数makeSound
function makeSound {
alert(this.sound)
}
现在我想对这两种动物都使用makeSound
。我所要做的就是通过给它一个上下文来调用这个函数。
makeSound.call(sheep) // -> Meaeeeeee
makeSound.call(dog) // -> woof-woof
this
帮助我为不同类型的对象重用此函数。这就是原型遗传的来源。