此Javascript原型片段的用途

时间:2013-08-14 19:51:00

标签: javascript

对不起,我不能说这个更好。但我遇到了一些如下代码:

MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;

我似乎无法弄清楚它的作用。 MyObject在上面定义如下:

function MyObject(options) {
    this.someProp = someDefault;
    this.otherProp = process(options.something);
    // etc...
}

并且它总是被称为构造函数。我只是想知道前两行提供什么好处,以及它是否是Javascript中的已知模式。

5 个答案:

答案 0 :(得分:2)

  

我似乎无法弄清楚它的作用

它会创建一个新对象,通过Object.create从[旧] MyObject.prototype继承,然后用它覆盖MyObject.prototype。它还明确添加了.constructor属性,该属性实际上应该已存在。

  

我只是想知道前两行提供的好处

没有,除非在该片段之前有人破坏了原型(如MyObject.prototype = Object.prototype),这是尝试修复它。

  

...如果它是Javascript中的已知模式。

不喜欢这样。使用Object.createinheritance between constructor-defined "classes" is a known pattern设置原型链,但然后构造函数在赋值的每一侧都会有所不同。

答案 1 :(得分:1)

我真的没有看到这样做有什么好处。

它正在做的是为新对象提供先前的对象方法。但它来自同一个对象......

以下是JS继承的一个很好的例子:

http://jsfiddle.net/aDCmA/2/

var App = (function(){
    var Being = function() {
        this.living = true;
        this.breathes = function () {
            return true;
        };
    };

    var Robert = function() {
        this.blogs = true;
        this.getsBored = function () {
            return "You betcha";
        }
    };
    Robert.prototype = new Being();

    return {
        Being: Being,
        Robert: Robert,
        being: function(){ return new Being(); },
        robert: function(){ return new Robert(); }
    }
}());

以下是另一个类似的问题:inherit prototype methods from other classes without overriding own prototype methods

感谢Robert Nyman最初的博客:http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/

答案 2 :(得分:1)

让我们逐行看:

MyObject.prototype = Object.create(MyObject.prototype);

这将MyObject.prototype重新定义为从MyObject.prototype继承的对象。这是不寻常的,因为从自身继承是没有意义的。

MyObject.prototype.constructor = MyObject;

由于上一行覆盖了MyObject.prototype,这只是修复了在进程中丢失的构造函数属性。

我可以想到一个可能有用的场景:如果之前的某些代码搞砸了MyObject.prototype,例如将另一个构造函数的原型分配给它:

MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.

然后您发布的代码将尝试修复它。

答案 3 :(得分:1)

提供的两行代码似乎是使用原型继承的不正确尝试,但我知道你要去哪里以及你想要实现的目标。

正如我们所知,JavaScript中有两种方法可以定义具有属性和方法作为成员的对象 - 对象文字符号和函数符号。使用对象文字表示法,我们无法立即访问new关键字(想象这就像在Java或C#中使用抽象类)。使用函数表示法,我们可以访问new关键字,因为作为函数的对象的初始声明充当我们的构造函数。

在ECMAScript 5中,Object对象被赋予了一个名为create的方法,该方法为开发人员提供了一种从使用对象文字符号声明的现有对象创建新对象的简单方法。 (参见文献here)。但是,以函数表示法创建的对象在此方法中存在问题,因为它们是Function对象。 Object.create方法是使用简单继承的好方法,允许访问基本属性和方法。

使用函数表示法,一旦使用new关键字,结果不是函数,而是对象。例如,我可以测试一下:

var Obj = function(){};
console.log(typeof Obj) // "function"

console.log(typeof new Object()); // "object"

因此,您只能继承一次(意味着无法从中派生子对象):

var MyObject = new Object();
var anotherObj = new MyObject() // throws exception

要缓解此问题,您需要执行以下三个步骤:

  1. 以函数表示法创建子对象(这样您就可以使用new关键字创建它的新实例并从中继承)。
  2. 将子对象的原型(对象)设置为基础对象的新实例的结果(也将是对象)。
  3. 将子对象的构造函数(恰好在对象的原型上)设置回引用自身的函数(这是实例化之前的函数)。如果不这样做,构造函数将仍然是一个对象,它不能生成新的实例。
  4. 从这里,您可以使用模式创建子对象和父对象的新实例,并从两者派生。这是一个实际的例子:

    var Vehicle = function(){};
    Vehicle.prototype.start = function() {
       return this.make + " " + this.model + " " + "started";
    }
    
    var Car = function(color, make, model) {
       this.color = color;
       this.make = make;
       this.model = model;
    }
    Car.prototype = new Vehicle();
    Car.prototype.constructor = Car; 
    
    var myCar = new Car("red", "chevy", "aveo");
    myCar.start(); //"chevy aveo started"
    

答案 4 :(得分:0)

这是完全有效的Javascript。

任何javascript函数(比如Func)都可以用作构造函数,构造函数调用也需要prototype属性(即F.prototype或与函数关联的原型)。因此(几乎)每个函数都有一个prototype属性。此属性的值(即Func.prototype)。

现在,与该函数关联的这个原型的值是一个对象本身,它有一个名为constructor的 non enumerable 属性。并且此构造函数属性的值是函数对象(即F本身)。

让我们举个例子。

假设我构建了一个函数Func

var Func = function() {
           //your definition
          };

既然可以将其作为构造函数调用,则必须使用prototype属性Func.prototype来调用此proto

proto = Func.prototype;

现在原型具有一个名为构造函数的单一属性(不可枚举)。此构造函数的值等于函数对象本身。

不要相信我这样检查

Func.prototype.constructor === Func // =>true

任何函数都会返回 true

现在来自您解释的代码: 所以基本上这两行

MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;

正在修改prototye的值,使其具有定义的值为MyObject的构造函数属性。但在正常情况下,这种情况无论如何都会发生。但原因可能是对象的prototype可能早于它继承的类的更改。在那种情况下,这两行是否有意义。

希望有所帮助:)