2011-08-11 45 views
2

使用Javascript - 权威指南(6ED)给出了下面的代码:复制属性在Javascript

本来我们有这个功能

/* 
* Copy the enumerable properties of p to o, and return o. 
* If o and p have a property by the same name, o's property is overwritten. 
* This function does not handle getters and setters or copy attributes. 
*/ 
function extend(o, p) { 
     for(prop in p) { // For all props in p. 
      o[prop] = p[prop]; // Add the property to o. 
     } 
     return o; 
} 

于是笔者决定重写,并延长复制能力(能复制存取性能,例如):

/* 
* Add a nonenumerable extend() method to Object.prototype. 
* This method extends the object on which it is called by copying properties 
* from the object passed as its argument. All property attributes are 
* copied, not just the property value. All own properties (even non- 
* enumerable ones) of the argument object are copied unless a property 
* with the same name already exists in the target object. 
*/ 
Object.defineProperty(Object.prototype, 
    "extend", // Define Object.prototype.extend 
    { 
     writable: true, 
     enumerable: false, // Make it nonenumerable 
     configurable: true, 
     value: function(o) { // Its value is this function 
      // Get all own props, even nonenumerable ones 
      var names = Object.getOwnPropertyNames(o); 
      // Loop through them 
      for(var i = 0; i < names.length; i++) { 
      // Skip props already in this object 
      if (names[i] in this) continue; 
      // Get property description from o 
      var desc = Object.getOwnPropertyDescriptor(o,names[i]); 
      // Use it to create property on this 
      Object.defineProperty(this, names[i], desc); 
      } 
    } 
}); 

我不明白为什么我们要扩大Object.prototype中 ,现在我们如何使用这个来复制的所有属性对象y对象x?我如何使用Object.prototype.extend

我决定测试一下我能否做得更快。我不明白为什么下面的自定义代码不起作用。

function extend(o){ 
    var p = new Object(); 
    for(prop in o) 
     Object.defineProperty(p,prop,Object.getOwnPropertyDescriptor(o,prop)); 
    return p; 

} 


// Let's perform a simple test 

var o = {}; 

Object.defineProperty(o, "x", { value : 1, 
    writable: true, 
    enumerable: false, 
    configurable: true}); 

o.x; // => 1 
Object.keys(o) // => [] 

var k = new Object(extend(o)); // Good, k.x => 1 

// More test 

Object.defineProperty(o, "x", { writable: false }); 
Object.defineProperty(o, "x", { value: 2 }); 
Object.defineProperty(o, "x", { get: function() { return 0; } }); 
o.x // => 0 

// Perform the creation again 

var k = new Object(extend(o)); // bad. k.x is 1, not 0 

// so the getter property didn't copy to k !!! 

对不起,我很新的Javascript。我在这里先向您的帮助表示感谢。所有这些问题都与“扩展”功能的转换/重写有关


我编辑了我的测试代码。抱歉!

+1

一个相当有名的'extend()'示例(检查jQuery源代码是如何工作的):http://api.jquery.com/jQuery.extend/和http://docs.jquery.com/教程:Getting_Started_with_jQuery –

回答

3

prototype定义这个的目的是让每一位Object可以调用它作为一个成员函数,就像这样:

yourobject.extend(anotherObject); 

大多数程序员发现更优雅不必通过这两个对象作为参数,像这样:

extend(yourObject, anotherObject); 

修改原型是向对象添加有用的“方法”的好方法。

旁白:我不会推荐使用作者的extend的代码。它没有正确检查hasOwnProperty

1

您似乎误解了prototype的使用。原型是JavaScript处理继承的方式。 extend函数是从C++和Java等语言借用的术语,并不是JavaScript的本地语言。

这里有prototype指南:http://mckoss.com/jscript/object.htm

我有几年的经验编写JavaScript和我建议不使用原型的。 JavaScript有其他处理数据建模的方法,我发现它更优雅。了解原型设计的工作原理仍然很有用,因为它加深了您对Objects的理解。

+1

这些还有哪些其他方法? –

+1

闭包。如果你不使用继承,你不需要原型。 – Halcyon