克罗克福德原型继承的一个小缺点

Minor drawback with Crockford Prototypical Inheritance

本文关键字:一个 缺点 原型 继承 克罗      更新时间:2023-09-26

只是在JS中尝试不同的继承技术,并且遇到了关于Crockford的原型继承模式的一些稍微令人不安的东西:

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}
var C,
    P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }
C = object(P);

这一切都很好- 除了当您登录到控制台时-对象显示为f -我看到过可以重新指向构造函数的经典模拟-是否有类似的方法来强制对象(控制台)引用?

问题是它引用了构造函数的name。这很快就变成了关于函数表达式、语句和name属性的讨论。事实证明,如果不使用eval,在运行时创建一个新的命名函数是完全不可能的。名称只能使用函数语句function fnName(){}来指定,并且除了对其求值之外,不可能动态地构造该代码块。var fnExpression = function(){}产生一个分配给变量的匿名函数。函数的name属性是不可变的,所以它是确定的。使用Function("arg1", "arg2", "return 'fn body';")也只能生成一个匿名函数,尽管它类似于eval。

这基本上只是JS规范中的一个疏忽(Brendan Eich说他后悔10年前那样定义显示名),ES6的解决方案正在讨论中。这将为为调试工具派生函数的显示名引入更多的语义,或者可能是一种显式的设置和调整它的方法。

现在你有一个路径:eval,或者其他形式的可配置代码的后期执行。

function displayName(name, o){
  var F = eval("1&&function "+name+"(){}");
  F.prototype = o; 
  return new F;
}

函数语句本身不会从eval返回,但会执行1 &&fnStatement将对象强制转换为可返回的表达式。

(Harmony代理还允许设置报告名称的函数,您可以在没有eval的情况下配置,但目前除了在Node.js和Firefox中不可用)。

我要在这里说明一下,所有那些被Crockford和其他许多人所嘲笑的"邪恶"函数都有它们的位置。eval, with,扩展本机都启用了特定的技术,否则这些技术是完全不可能的,在适当的场合使用它们并没有错。很可能大多数人都没有资格判断什么时候是正确的。在我看来,在等待解决方案的同时,无害地使用eval来弥补糟糕的语言语义和工具是完全可以接受的,只要您不将任意代码汇集到eval语句中,就不会对您造成任何伤害。

如果我记录对象,我可以看到:Object { foo="bar", baz=function()},所以我不明白你的问题…

无论如何,可以使用Object.create()来代替Crockford的函数:

var P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }
var C = Object.create (P);

console.log (C):

Object { foo="bar", baz=function()}