【问题标题】:Inheriting objects继承对象
【发布时间】:2011-10-08 14:37:35
【问题描述】:

我读到Javascript的继承是原型的。这是什么意思?程序员定义的对象如何继承预定义对象的属性,例如window? 例如,我需要在我自己的类中使用函数 eval() 。如何实现?

【问题讨论】:

  • 为什么要继承eval?在代码中使用 eval 有 99.99% 的情况是错误的。
  • 出于什么目的需要继承 eval? ECMAScript 第 5 版规范对 eval 以间接方式使用时的行为进行了语义更改 - 就像我认为您愿意使用它的方式一样,例如myObj.eval-, eval 无法访问调用者的变量/词法环境,它使用全局环境。只有直接的eval 调用才能访问调用者的词法环境。

标签: javascript class scope prototypal-inheritance


【解决方案1】:

抛开您是否应该window继承的问题,这里有一个简单的例子来说明如何做到这一点:

function Test() {
    // constructor code
}

Test.prototype = window;

var t = new Test();
t.eval();

当使用new 运算符调用时,Test 函数会创建一个Test 的新实例,其原型链接到window 对象。函数的原型可以是任何对象。

【讨论】:

    【解决方案2】:

    Protip:不要使用new 来声明对象。 Object.create 是创建 JavaScript 对象的正确方法。所有现代浏览器都支持它。对于其他浏览器,本文底部有一个不错的 shim:

    http://javascript.crockford.com/prototypal.html

    使用'new'的构造函数的一个问题是,如果人们不小心像普通函数一样调用它,它将使用变量this对全局变量(即,如果在浏览器中的窗口)进行修改,所以@987654326 @应该只保留给原型函数,我更喜欢使用that而不是this

    我个人使用一种支持new obj()obj()obj.init()的样式,这可能是一个额外的函数指针,但我认为它增加了语义意义

    function obj(){
        var that = Object.create(obj.prototype)
        //any constructor logic goes here
        return that
    }
    obj.prototype = Object.create(Superclass.prototype)
    
    obj.init = obj //completely optional
    
    //other function declarations
    
    obj.prototype.someFunction = function(){
        //logic for someFunction
    }
    

    【讨论】:

    • create() 是标准 Javascript 库的一部分吗?还是像这样的框架的一部分?prototypejs.org/api/class/create
    • @user822982, Object.create 是 ECMAScript 第 5 版规范的一部分,但它是 not completely emulable on ECMAScript 3 实现,Crockford 的 Object.create shim 无法处理第二个参数,用描述符定义属性,它不能创建继承自 null 的对象。
    【解决方案3】:

    您到底想达到什么目的? 这是原型继承的最简单(不是最好)的方法:

    var obj1=new Object1Constructor();
    var obj2=new Object2Constructor();
    
    obj2.prototype=obj1;
    

    表示obj1继承了obj2的所有属性

    我忘记了主要的事情:eval==evil;

    更新: 我在上面的代码中犯了错误。那不是继承。这是更新的代码:

    var Object1Constructor=function(){ // one object constuctor
        //properties definition goes here
    }
    
    var Object2Constructor=function(){ // another object constuctor
        //properties definition goes here
    }
    
    Object2Constructor.prototype=new Object1Constructor();
    
    var obj=new Object2Constructor();
    

    这就是继承。现在obj 具有在Object2ConstructorObject1Constructor 中定义的属性 - 父“类”。 请参阅下面的 CMS 评论。他是完全正确的。

    【讨论】:

    • prototype 属性只与函数对象相关——当用作构造函数时——你不能像这样设置obj2[[Prototype]] 内部属性,你只是在创建一个名为"prototype" 的属性(与继承无关)。 更改 已初始化对象[[Prototype]] 的唯一方法是通过非标准且已弃用的__proto__ 属性。有关prototype[[Prototype]] 的更多信息:JavaScript prototype limited to functions ??
    • 是的。你说的对。请查看更新的代码。现在正确吗?
    • 是的,现在看起来不错,我只需将Object2Constructor.prototypeconstructor 属性在替换后设置回Object2Constructor,否则您的示例中的obj.constructor 将引用@987654341 @ (另外,我也会在函数表达式的末尾添加分号 - 或者改用函数定义 - 但这不是完全必需的)。
    猜你喜欢
    • 2012-01-05
    • 2013-01-04
    • 2019-01-30
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多