9

只是在 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。我已经看到了可以重新指向构造函数的经典仿真-是否有类似的方法来强制对象(控制台)引用?

4

2 回答 2

14

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

这基本上只是 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 Proxies 还允许设置报告名称的函数,您可以在没有 eval 的情况下进行配置,但目前除了在 Node.js 和 Firefox 中之外不可用)。

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

于 2011-11-10T08:10:42.450 回答
0

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

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

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

var C = Object.create (P);

控制台日志(C):

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

于 2012-03-06T15:12:21.093 回答