有趣的JavaScript继承模式

时间:2017-08-30 15:04:41

标签: javascript inheritance prototype

我最近观看过Douglas Crockford正在解释Javascript继承模式的视频。视频本身很老 - 它是在6年前拍摄的 - 但仍然有用。在那段视频中,他展示了一种他发明的遗传模式(尽管我不确定作者是谁)。这是使用他的方法的代码:

Dim Arg, var1, var2
Set Arg = WScript.Arguments

Set objStdOut = WScript.StdOut
Set objStdErr = WScript.StdErr

var1 = Arg(0)
var2 = Arg(1)

if var2 = 2 then
**do stuff**
objStdOut.Write "Msg 1"
End if

set Arg = Nothing

不幸的是,他没有展示调用。那么,这部分

// imitation of new operator
function objectConstructor(obj, initializer, methods) {
    // create prototype
    var func, prototype = Object.create(obj && obj.prototype);
    // add methods to the prototype
    if(methods) Object.keys(methods).forEach(function(key) {
        prototype[key] = methods[key];
    });
    // function that will create objects with prototype defined above
    func = function() {
        var that = Object.create(prototype);
        if(typeof initializer === 'function') initializer.apply(that, arguments);
        return that;
    }
    
    func.prototype = prototype;
    prototype.constructor = func;
    return func;
}

var person = objectConstructor(Object, function(name) {
    this.name = name;
},  {
    showName: function() {
        console.log(this.name);
    }
});
var employee = objectConstructor(person, function(name, profession) {
    this.name = name;
    this.profession = profession;
},  {
    showProfession: function() {
        console.log(this.profession);
    }
});
var employeeInfo = employee('Mike', 'Driver');
employeeInfo.showName(); // Mike
employeeInfo.showProfession(); // Driver

是我的。它通常有效,但事实证明,我对两个“类”重复var employeeInfo = employee('Mike', 'Driver'); employeeInfo.showName(); employeeInfo.showProfession(); - this.name = name;person。我玩了一下,但没有重复,我没有设法让它正常工作。似乎我无法获得employee,因为name的原型链中不包含此类属性。我没有成功地混合employee这样的东西。因此,除了2017年是否酷/好/聪明/明智等,我如何从person.call(this, arguments)删除this.name = name;并获得相同的结果?或者一切都很好,这种方法不是假设的吗?

2 个答案:

答案 0 :(得分:1)

由于func 构造函数完全忽略this,因此通过callapply向其传递任何上下文都不起作用。创建一种复制 super 类的方法'创建对象后的属性是完成任务的方法之一。



// imitation of new operator
function objectConstructor(obj, initializer, methods) {
    // create prototype
    var func, prototype = Object.create(obj && obj.prototype);
    // add methods to the prototype
    if(methods) Object.keys(methods).forEach(function(key) {
        prototype[key] = methods[key];
    });
    // function that will create objects with prototype defined above
    func = function() {
        var that = Object.create(prototype);
        if(typeof initializer === 'function') initializer.apply(that, arguments);
        return that;
    }
    
    func.prototype = prototype;
    prototype.constructor = func;
    return func;
}

function copyProperties(source, target) {
  for (var prop in source) {
    if (source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }
}

var person = objectConstructor(Object, function(name) {
    this.name = name;
},  {
    showName: function() {
        console.log(this.name);
    }
});
var employee = objectConstructor(person, function(name, profession) {
    copyProperties(person.apply(null, arguments), this);
    this.profession = profession;
},  {
    showProfession: function() {
        console.log(this.profession);
    }
});
var employeeInfo = employee('Mike', 'Driver');
employeeInfo.showName(); // Mike
employeeInfo.showProfession(); // Driver




答案 1 :(得分:1)

这是您的代码段,包含2个小修改,以便您可以执行超级(姓名)类型的调用。

我已经发表评论了我已经做了修改..用前缀keith:



// imitation of new operator
function objectConstructor(obj, initializer, methods) {
    // create prototype
    var func, prototype = Object.create(obj && obj.prototype);
    // add methods to the prototype
    if(methods) Object.keys(methods).forEach(function(key) {
        prototype[key] = methods[key];
    });
    // function that will create objects with prototype defined above
    func = function() {
        var that = Object.create(prototype);
        if(typeof initializer === 'function') initializer.apply(that, arguments);
        return that;
    }
    
    func.prototype = prototype;
    //keith: store the initialization in constructor,
    //keith: as func is already creating the object..
    prototype.constructor = initializer;
    return func;
}

var person = objectConstructor(Object, function(name) {
    this.name = name;
},  {
    showName: function() {
        console.log(this.name);
    }
});
var employee = objectConstructor(person, function(name, profession) {
    //keith: call our super  person(name)
    person.prototype.constructor.call(this, name);
    this.profession = profession;
},  {
    showProfession: function() {
        console.log(this.profession);
    }
});
var employeeInfo = employee('Mike', 'Driver');
employeeInfo.showName(); // Mike
employeeInfo.showProfession(); // Driver