gpt4 book ai didi

javascript - 在Javascript中, 'Object.create'和 'new'的区别

转载 作者:数据小太阳 更新时间:2023-10-29 05:19:50 25 4
gpt4 key购买 nike

我认为差异已经在我脑海中闪过,但我只是想确定一下。

在 Douglas Crockford 页面上 Prototypal Inheritance in JavaScript , 他说

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.

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

这是测试:

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.

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

最佳答案

您的假设是正确的,但还有另一种模式 Douglas 没有过多谈论 - 原型(prototype)也可用于属性。你的 person 类可以写成:

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;};

在这种情况下,如您在示例中所做的那样,遍历此类实例的属性不会为“性别”属性生成任何输出。

编辑 1:在构造函数中分配 name 和 age do 使属性对 hasOwnProperty 可见(感谢 @matt 提醒我这一点)。未分配的性别属性在有人在实例上设置之前是不可见的。

编辑 2:为了进一步补充这一点,我提出了另一种继承模式——我个人曾在非常大的项目中使用过的模式:

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;
}

这是一个相当常见的模式,有一个小的变化——父类通过“父类(super class)”属性附加到子类,允许您访问被子类覆盖的方法/属性。从技术上讲,您可以将 OldPerson.superclass 替换为 Person,但这并不理想。如果您曾将 OldPerson 更改为继承自 Person 以外的类,则还必须更新对 Person 的所有引用。

编辑 3:只是为了带来这个完整的循环,这里是“继承”函数的一个版本,它利用了 Object.create 并且功能与我之前描述的完全相同:

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

关于javascript - 在Javascript中, 'Object.create'和 'new'的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10361803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com