3

我正在研究 CodeAcademy JS 练习,并对这个示例有疑问:

//Animal class
function Animal(name) {
    this.name = name;
}

//Attach sayName method to Animal class
Animal.prototype.sayName = function() {
    console.log("Hi my name is " + this.name);
};

//create an animal object instance
var dog = new Animal('Barker');

//invoke a method attached to the prototype from the object instance
dog.sayName();

我对这段代码的理解是:

  1. 由于在调用函数之前使用了 new 关键字,JS 创建了一个新的 Animal 对象实例,var dog 指向该实例Animal()- 函数构造函数
  2. var dog 对象的原型sayName()在以下行中附加了方法:Animal.prototype.sayName = function()
  3. 由于sayName()已附加到类prototype,因此该方法现在可用于Animal通过使用new Animal()函数构造函数从类创建的任何对象

这是对这段代码发生的事情的正确理解吗?

另外,我试图了解如何this指向 Animal 对象this.name

Animal.prototype.sayName = function() {
    console.log("Hi my name is " + this.name);
};

Animal.prototype指向一个实际的对象:prototype这个Animal对象实例的对象?如果是这样,不应该指向, 因为this实际上是从?this.nameAnimal.prototypesayName()Animal.prototype

我对上下文的理解this是它this总是指向调用函数的对象。但是,在这种情况下,whendog.sayName()被调用,this指向Animal,这就是当它被记录到控制台时的this.name相等性。'Barker'我猜要么我误解了 Animal.prototype 指向原型对象,要么 JSdog.sayName()this将方法附加到prototype.

在这个小例子中有多个问题,但准确掌握这里发生的事情将真正有助于我理解这些基本概念。

4

3 回答 3

2

[点1-3]

这是对这段代码发生的事情的正确理解吗?

是的,听起来你明白了。

Animal.prototype 不是指向一个实际的对象:prototype这个Animal对象实例的对象吗?

是的,prototype对象是一个Object实例。

如果是这样,不应该指向, 因为this实际上是从?this.nameAnimal.prototypesayName()Animal.prototype

不,因为您将其称为dog.

dog.sayName();

如果你这样称呼它,那么是的,this会引用Animal.protoype.

Animal.protoype.sayName();

但这不会很有用。

我对上下文的理解this是它this总是指向调用函数的对象。

不完全的。大多数情况this下是指调用该方法的对象,而不是它的属性对象。一个方法实际上可以是多个对象的属性,因此this动态地指向它作为方法调用的对象。

当然,this可以在其他上下文中引用其他事物,例如不作为方法调用时,或者在绑定函数中使用.bind.

于 2016-04-09T18:55:21.983 回答
1

你误会了this。创建函数时未设置的值this,它是一个附加参数。每次调用函数时,this值都会发生变化。

在方法的情况下,该this值设置为基础对象。例如,

dog.sayName(); // `this` is `dog`
({sayName: dog.sayName}).sayName(); // `this` is this new object
(0,dog.sayName)(); // `this` is undefined or the global object
于 2016-04-09T18:55:02.670 回答
1

thisJavascript 中有两个明显的特征,会引起很多混乱:

  1. 它是该语言唯一的动态范围内建功能
  2. 它被视为隐式参数

词法范围

var i = 0;
const inc = () => i + 1;

const inc2 = x => {
  var i = x;
  return inc();
};

inc2(100); // 1

动态范围

var o = {
  i: 0,
  inc: function () { return this.i + 1 }
};

var p = {
  i: 100,
  inc2: o.inc
};

p.inc2(); // 101

this是动态范围的,因为它是通过调用上下文设置的。

隐式参数

this它不是作为形式参数显式传递给方法,而是被隐式处理。因此,您需要使用call/apply设置不同的值(即对象)this

// Note that s and t are implicitly converted to objects

const split = (o, x) => o.split(x);
let s = "1,2,3", t = "4,5,6";

// objects are passed explicitly as normal arguments
split(s, ","); // ["1", "2", "3"]
split(t, ","); // ["4", "5", "6"]

// objects (or this) are provided implicitly
s.split(","); // ["1", "2", "3"]
s.split.call(t, ",") // ["4", "5", "6"]

想象this成一个方法的接收对象,它必须作为第一个参数传递。

于 2016-04-10T08:56:05.773 回答