在Javascript中,'Object.create'和'new'之间的区别 [英] In Javascript, the difference between 'Object.create' and 'new'

查看:97
本文介绍了在Javascript中,'Object.create'和'new'之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为差异已经点击了我的脑袋,但我想确定一下。

I think the difference has clicked in my head, but I'd just like to be sure.

在Douglas Crockford页面上 JavaScript中的Prototypal继承,他说

On the Douglas Crockford page Prototypal Inheritance in JavaScript, he says


在原型系统中,对象从对象继承。然而,JavaScript,
缺少执行该操作的运算符。相反,
有一个新的运算符,这样新的f()就会产生一个
继承自f.prototype的新对象。

In a prototypal system, objects inherit from objects. JavaScript, however, lacks an operator that performs that operation. Instead it has a new operator, such that new f() produces a new object that inherits from f.prototype.

我真的不明白他在那句话中想说的是什么,所以我进行了一些测试。在我看来,关键的区别在于,如果我在纯原型系统中基于另一个对象创建一个对象,那么所有父父成员应该在新对象的原型上,而不是在新对象本身上。

I didn't really understand what he was trying to say in that sentence so I performed some tests. It seems to me that the key difference is that if I create an object based on another object in a pure prototypal system, then all the parent parent members should be on the prototype of the new object, not on the new object itself.

这是测试:

var Person = function(name, age) {
        this.name = name;
        this.age = age;
}
Person.prototype.toString = function(){return this.name + ', ' + this.age};

// The old way...
var jim = new Person("Jim",13);
for (n in jim) {
    if (jim.hasOwnProperty(n)) {
        console.log(n);
     }
}
// This will output 'name' and 'age'.

// The pure way...
var tim = Object.create(new Person("Tim",14));
for (n in tim) {
    if (tim.hasOwnProperty(n)) {
        console.log(n);
     }
}
// This will output nothing because all the members belong to the prototype.
// If I remove the hasOwnProperty check then 'name' and 'age' will be output.

我的理解是正确的,只有在测试对象本身的成员时差异才会变得明显吗?

Is my understanding correct that the difference only becomes apparent when testing for members on the object itself?

推荐答案

你的假设是正确的,但道格拉斯并没有太多谈论的另一种模式 - 原型可以用作属性好。您的人员课程可以写成:

Your assumptions are correct, but there is another pattern that Douglas doesn't talk much about - the prototype can be used for properties as well. Your person class could have been written as:

var Person = function(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.name = null; //default value if you don't init in ctor
Person.prototype.age = null;
Person.prototype.gender = "male";
Person.prototype.toString = function(){return this.name + ', ' + this.age;};

在这种情况下,迭代这个类的实例的属性,就像在你的例子中一样,不会为'gender'属性生成任何输出。

In this case, iterating over properties of an instance of this class, as you do in your example, would generate no output for the 'gender' property.

编辑1:
构造函数中的名称和年龄的分配使得属性可以通过hasOwnProperty显示(感谢@matt提醒我这个)。在有人在实例上设置之前,未分配的性别属性将不可见。

EDIT 1: The assignment of name and age in the constructor do make the properties visible by hasOwnProperty (thanks @matt for reminding me of this). The unassigned gender property would not be visible until someone sets it on the instance.

编辑2:
为了进一步添加到此,我提出了另一种继承模式 - 我个人用于大型项目的一个:

EDIT 2: To further add to this, I present an alternative inheritance pattern - one that I have personally used for very large projects:

var inherits = function(childCtor, parentCtor) {
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  childCtor.superclass = parentCtor.prototype; 
  childCtor.prototype = new tempCtor();
  childCtor.prototype.constructor = childCtor;
};

var Person = function(name){
    this.name = name;
}
Person.prototype.name = "";
Person.prototype.toString = function(){
    return "My name is " + this.name;
}

var OldPerson = function(name, age){
    OldPerson.superclass.constructor.call(this);
    this.age = age
};
inherits(OldPerson, Person);
OldPerson.prototype.age = 0;
OldPerson.prototype.toString = function(){
    var oldString =  OldPerson.superclass.toString.call(this);
    return oldString + " and my age is " + this.age;
}

这是一个相当常见的模式,有一点点扭曲 - 父类是附加的通过超类属性向孩子发送,允许您访问由孩子覆盖的方法/属性。从技术上讲,你可以用 Person 替换 OldPerson.superclass ,但这并不理想。如果您曾将OldPerson更改为继承Person以外的类,则必须更新对Person的所有引用。

This is a fairly common pattern with a small twist - the parent class is attached to the child via the "superclass" property permitting you to access methods/properties overridden by the child. Technically, you could replace OldPerson.superclass with Person, however that is not ideal. If you ever changed OldPerson to inherit from a class other than Person, you would have to update all references to Person as well.

编辑3:
只是为了带上这个完整的圆圈,这里是inherits函数的一个版本,它利用了Object.create和函数与我之前描述的完全相同:

EDIT 3: Just to bring this full circle, here is a version of the "inherits" function which takes advantage of Object.create and functions exactly the same as I previously described:

var inherits = function(childCtor, parentCtor) {
    childCtor.prototype = Object.create(parentCtor.prototype);
    childCtor.superclass = parentCtor.prototype; 
};

这篇关于在Javascript中,'Object.create'和'new'之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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