使用Object.create(),样本应该在他们的'原型'上附加方法。属性?

时间:2014-03-28 19:51:42

标签: javascript oop prototypal-inheritance

我一直在阅读Is JavaScript's "new" keyword considered harmful?this Adobe Article on using prototypal inheritance rather than 'new'。 Adobe文章有一个“新”示例:

function Foo() {
    this.name = "foo";
}
Foo.prototype.sayHello = function() {
    alert("hello from " + this.name);
};

......它取代了:

var foo = {
    name: "foo",
    sayHello: function() {
        alert("hello from " + this.name);
    }
};

此处'sayHello'方法未附加到对象的prototype。这是不是意味着'sayHello'在内存中不必要地重复(我知道V8避免了这种情况,但在旧的JS引擎中),因为它被复制到从foo继承的所有对象?

不应该是:

var foo = {
    name: "foo",
    prototype: {
        sayHello: function() {
            alert("hello from " + this.name);
        }
    }
};

或者类似的?

3 个答案:

答案 0 :(得分:2)

该方法未附加到原型,因为此对象成为使用Object.create附加到新创建的对象的原型。而且你不需要原型的原型。

请记住,Object.create不会深层克隆对象。相反,它等同于

Object.create = function(proto) {

   function F() {}
   F.prototype = proto;
   return new F();

}

(实际实施更复杂,但这个简短的版本说明了这个想法)

所有新创建的对象都“继承”foo中的方法,该方法充当原型,此处没有重复。

答案 1 :(得分:2)

不,如果您使用它作为原型创建另一个对象,它将不会重复。使用Object.create的几乎等效的代码实际上略有不同,你没有使用原型,你只是创建一个对象。 To use prototypal inheritance, do the following。请注意,使用new仍会设置原型链,因此您链接到的文章的标题不是很准确,并且您仍然在单个对象上共享属性。

var foo = {
    name: "foo",
    sayHello: function() {
        alert("hello from " + this.name);
    }
};

var extended = Object.create(foo);
var extended2 = Object.create(foo);

extended.name = "first";
extended2.name = "second";
extended.sayHello();  // hello from first
extended2.sayHello(); // hello from second

// Methods are shared, outputs true
console.log(extended.sayHello === extended2.sayHello)

// Now if you delete the property again, it will go up the chain
delete extended.name;
extended.sayHello(); // hello from foo

您也可以这样做

var extended = Object.create(Foo.prototype);

如果您创建构造函数来获取新实例而不是Object.createnew Foo

,那么它将会重复
function createFoo() {
    return {
        name: "foo",
        sayHello: function() {
             alert("hello from " + this.name);
        }
    }
}

var a = createFoo();
var b = createFoo();
 // The function objects are not shared    
alert('Are functions the same? ' + a.sayHello === b.createFoo);

如果使用闭包方法创建对象,也不会共享它们。克罗克福德建议创建真正的私人成员。我不使用它,因为它不使用原型链,并且继承是很难实现的,而不仅仅是复制属性。

Function Foo() {
    var name = 'foo';
    this.sayHello = function () {
        alert(name);
    };
    this.setName = function (newName) {
        name = newName;
    };
}

var a = new Foo();
var b = new Foo();
console.log(a.sayHello === b.sayHello); // outputs false

答案 2 :(得分:0)

在这里回答我自己的问题,为了我自己的笔记,并帮助向他人解释:

  

Q值。使用Object.create(),样本是否应该将方法附加到prototype属性?

:一种。不,因为Object.create(parentObject)本身将parentObject设置为动态创建的构造函数的prototype

另外:prototype始终是构造函数的属性 - 而不是常规对象。例如:

var someArray = [];
someArray.__proto__ === Array.prototype

Object.create()动态创建构造函数,将它们的原型设置为第一个参数中的对象。