我可以简化此构造函数的实例化吗?



是否可以将以下代码(尤其是new关键字(分解为更简单的代码(以便我了解发生了什么(?

function F() {
this.color = 'red';
this.printNumber = function printNumber() {
console.log(5);
};
}
let o = new F();
console.log(o);

这是我的尝试:

当我被告知let o = new F();let o = F.call({})相同时,我以为我是赢家,但我可以在控制台上看到,第一个还给空对象一个设置为构造函数的constructor属性。

新对象将构造函数属性设置为构造函数是否非常重要?我知道这个构造函数将被视为一种方法,其中的this将引用整个对象。这让我认为new的工作原理是:

立即创建将构造函数
  1. 属性设置为构造函数的对象。
  2. 执行构造函数属性(方法(,使新对象如下所示:
{
color: "red",
printNumber: printNumber,
constructor: F
//as it is an instance of the inbuilt Object constructor function, it has all the properties/methods of an object
}

新对象具有构造函数属性是否非常重要 设置为构造函数?

如果您的目的是创建一个可以实例化和继承的对象,那么是的,您应该使用new语法。call()这样做,它会调用函数(运行其代码(,而无需正式实例化对象的实例。call()还允许您定义函数运行时this将绑定到的内容,但call()new并不相同。

使用new实例化时,将创建对象的实例并执行构造函数。 然后this绑定到新实例。

有关new和原型继承如何工作的更多详细信息,请参阅我的另一篇文章。

另外,仅供参考,您应该将对象的方法(无论您拥有哪个特定实例都运行相同(添加到对象的prototype,而不是对象本身:

function F() {
this.color = 'red';
}
// Methods are usually added just once to the object's
// prototype and then all instances inherit it, which
// has a lower memory footprint because the method is
// defined and attached just once instead of on each 
// instance.
F.prototype.printNumber = function printNumber() {
console.log(5);
};
let o = new F();
console.log(o.color);
o.printNumber();

使用new关键字调用构造函数时,会发生以下情况:

  1. 将创建一个新的空对象并将其分配给this
  2. 函数体执行。通常它会修改this,为其添加新属性。
  3. 返回this的值。

返回对象在其原型中具有引用构造函数的constructor属性。

现在为什么原型中的构造函数很重要?这完全与 JS 中的对象继承模式有关。

//Here is the Animal constructor
function Animal() {
this.live  = true;
}
//Object methods are attached to the prototype. So, they have a single presence in the object hierarchy
Animal.prototype.move = function() {console.log('moving')}; 

//Here is the Cat constructor. This is how JS makes the Cat inherit from the animal.
function Cat() {
Animal.call(this);   //The this keyword points to the Cat object being created
}
//Let's set its prototype
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

//All is set. Let's create the child object    
let cat = new Cat();

以下是事件的顺序。

声明
  1. 了简单的动物构造函数。它将为每只动物增加live=true

  2. 它的原型具有move方法。因此,任何动物都可以移动,并且此移动功能不会被实例化 - 因为它在原型中 - 而不是this.

  3. 定义 Cat 构造函数。它简单地调用Animal构造函数而不new。因此,它不会创建动物 - 但它将在结果对象中创建所有动物属性。

  4. 将动物设置为猫的原型。请注意,它继承了 Animals 原型方法 - 即move。这就是为什么我们说javascript具有原型继承。

  5. 将 Cat 构造函数设置为 Cat。这是因为在第 4 点,Cat 的构造函数也是 Animal。我们在这里更改它。(是的 - 奇怪(

  6. 创建一个新猫。这将call没有new的动物构造函数,因此,猫具有所有动物属性。猫可以移动 - 因为它的原型具有move方法。最后,构造函数不是 Cat - 所以,new关键字将使用它。


新的 Ecmascript 版本将这一切包装在Class中,并自动执行操作。但我相信,基本理解也很重要。

最新更新