使用Object.assign和Object.create进行继承 [英] Using Object.assign and Object.create for inheritance

查看:109
本文介绍了使用Object.assign和Object.create进行继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通常按以下几行实现继承。

I typically implement inheritance along the following lines.

function Animal () { this.x = 0; this.y = 0;}

Animal.prototype.locate = function() { 
  console.log(this.x, this.y);
  return this;
};
Animal.prototype.move = function(x, y) {
  this.x = this.x + x;
  this.y = this.y + y; 
  return this;
}


function Duck () {
    Animal.call(this);
}

Duck.prototype = new Animal();
Duck.prototype.constructor = Duck;
Duck.prototype.speak = function () {
    console.log("quack");
    return this;
}

var daffy = new Duck();

daffy.move(6, 7).locate().speak();

我读过 Eric Elliott的这篇文章如果我理解正确,我可以使用 Object.create Object.assign 而不是?它真的那么简单吗?

I've read this post by Eric Elliott and if I understand correctly I can use Object.create and Object.assign instead? Is it really that simple?

var animal = {
   x : 0,
   y : 0,
   locate : function () { 
     console.log(this.x, this.y);
     return this;
   },
   move : function (x, y) { 
     this.x = this.x + x; 
     this.y = this.y + y;
     return this;
   }
}

var duck = function () {
   return Object.assign(Object.create(animal), {
     speak : function () { 
       console.log("quack");
       return this;
     }
   });
}

var daffy = duck();

daffy.move(6, 7).locate().speak();

顺便说一句,按照惯例,构造函数是大写的,如果作为构造函数的对象文字也是大写的?

As an aside, by convention constructor functions are capitalized, should object literals that act as constructors also be capitalized?

我发现这里有很多问题讨论 new Object.create ,但它们通常似乎与 Duck.prototype = new Animal(); 相对于 Duck.prototype = Object.create( Animal.prototype);

I realise there are many questions here discussing new versus Object.create, but they typically seem to relate to Duck.prototype = new Animal(); versus Duck.prototype = Object.create(Animal.prototype);

推荐答案

是的,就这么简单。在使用 Object.create / Object.assign 的示例中,您正在使用工厂函数来创建 duck 的新实例(类似于jQuery创建新实例的方式,如果你选择一个元素 var body = $('body'))。这种代码风格的一个优点是,当你想要创建一个新的 duck时,它不会强迫你调用 animal 的构造函数实例(与ES2015类相对)。

Yes, it is that simple. In your example with Object.create/Object.assign, you are using a factory function to create new instances of duck (similar to the way jQuery creates new instances if you select an element with var body = $('body')). An advantage of this code style is, that it doesn't force you to call a constructor of animal when you want to create a new duck instance (as opposed to ES2015 Classes).

初始化差异

也许一个有趣的小问题与你使用构造函数(或任何其他初始化函数)的工作方式略有不同:

Maybe one interesting tidbit that works slightly differently than if you were to use a constructor (or any other initialization function):

创建<$ c时$ c> duck instace, animal 的所有属性都在 [[Prototype]] duck 实例的插槽。

When you create a duck instace, all the properties of animal are in the [[Prototype]] slot of the duck instance.

var daffy = duck();
console.log(daffy); // Object { speak: function() }

所以 daffy 还没有任何自己的 x y 属性。但是,当您拨打以下电话时,会添加以下内容:

So daffy does not have any own x and y properties yet. However, when you call the following, they will be added:

daffy.move(6, 7);
console.log(daffy); // Object { speak: function(), x: 6, y: 7 }

为什么?在 animal.move 的函数体中,我们有以下语句:

Why? In the function-body of animal.move, we have the following statement:

this.x = this.x + x; 

所以当你用 daffy.move ,指的是 daffy 。因此它会尝试将 this.x + x 分配给 this.x 。由于 this.x 尚未定义, [[原型]] daffy 遍历到 animal ,其中定义了 animal.x

So when you call this with daffy.move, this refers to daffy. So it will try to assign this.x + x to this.x. Since this.x is not yet defined, the [[Prototype]] chain of daffy is traversed down to animal, where animal.x is defined.

因此,在第一次调用中,赋值右侧的 this.x 指的是动物.x ,因为未定义 daffy.x 。第二次调用 daffy.move(1,2),右侧的 this.x daffy.x

Thus in the first call, the this.x on the right side of the assignment refers to animal.x, because daffy.x is not defined. The second time daffy.move(1,2) is called, this.x on the right side will be daffy.x.

替代语法

或者,您也可以使用 Object.setPrototypeOf 而不是 Object.create / Object.assign OLOO Style ):

Alternatively, you could also use Object.setPrototypeOf instead of Object.create/Object.assign (OLOO Style):

var duck = function () {
   var duckObject = {
       speak : function () { 
           console.log("quack");
           return this;
       }
   };
   return Object.setPrototypeOf(duckObject, animal);
}

命名约定

我不知道任何既定的惯例。 Kyle Simpson在OLOO中使用大写字母,Eric Elliot似乎使用小写字母。我个人会坚持使用小写,因为充当构造函数的对象文字已经是完全成熟的对象本身(不仅仅是蓝图,就像类一样)。

I'm not aware of any established conventions. Kyle Simpson uses uppercase letters in OLOO, Eric Elliot seems to use lowercase. Personally I would stick with lower-case, because the object literals that act as constructors are already fully fledged objects themselves (not just blueprint, like classes would be).

Singleton

如果您只想要一个实例(例如单个实例),您可以直接调用它:

If you only wanted a single instance (e.g. for a singleton), you could just call it directly:

var duck = Object.assign(Object.create(animal), {
    speak : function () { 
        console.log("quack");
        return this;
    }
});

duck.move(6, 7).locate().speak();

这篇关于使用Object.assign和Object.create进行继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆