7

这个问题刚刚得到了投票,所以可以用我所做的更新问题

我通过迭代窗口对象(或用户指定的对象根)来解决它,当我找到正确的实例时,我回溯并从索引中获取名称。最终解决方案可以在这里找到

https://github.com/AndersMalmgren/Knockout.BindingConventions

更新结束

我正计划为 KnockoutJS / MVC 编写一个关于配置模板源引擎的约定。我从一个小的客户端 POC 开始,马上就遇到了一个表演障碍

我的计划是使用这种语法或类似的东西

MyApp.EditCustomersViewModel = function() {
   ko.templates.loadView(this);
};

执行此操作时,它将检查模板缓存或使用对象名称作为键从服务器获取模板。问题是我无法获得原型对象的名称,我试过这个

Object.prototype.getName = function() {
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

如果适用于这样定义的对象

function MyClass() { 
}

如果您将原型添加到上述对象,它将不起作用,或者如果您像这样定义它

MyApp = {};
MyApp.MyClass = function() {
};

原型和范围界定是两个必须的,所以这是一个很好的展示,有什么想法吗?

小提琴:http: //jsfiddle.net/aRWLA/

编辑:这个的背景是这样的。

在服务器上你有这样的结构

  • 模板\ [视图名称]\index.html
  • 模板\ [视图名称]\sub-model-template.html

在客户端你会做

MyApp.EditCustomersViewModel = function() {
   ko.templates.loadView(this);
};

这将生成一个以对象名称为键的 ajax 请求,它将获取相关视图的所有模板

4

4 回答 4

4

只有提升的函数 ( function someFunc() {) 具有可检索的名称。

分配的函数不会,因为从技术上讲,您不是在命名函数,而是创建一个匿名函数并将对它的引用(在内存中)分配给命名变量。

因此,命名的是 var,而不是函数。

这使得检索函数名称的想法几乎无法启动,因为在任何模糊成熟的模式中,您将编写方法,而不是提升函数 - 当然方法是分配函数。

命名表达式(请参阅其他答案)是一种部分解决方法,但这些还有其他问题 - 尤其是在较旧的 IE 中缺乏支持。

(旁注:我一直期望浏览器供应商围绕这一点进行构建,以便分配函数的名称变得可检索,但 AFAIK 还没有喜悦。)

于 2012-08-24T08:55:39.517 回答
2

我认为您在替换函数原型时存在问题:如果替换函数原型对象,则必须constructor在原型中保留成员:

function Test1() {
}
Test1.prototype={
  constructor: Test1
};

MyApp={};
MyApp.MyClass=function MyClass(){
};
MyApp.MyClass.prototype={
  constructor: MyApp.MyClass
};

你的例子:http: //jsfiddle.net/aRWLA/1/

修改示例:http: //jsfiddle.net/aRWLA/2/

于 2012-08-23T11:15:12.507 回答
1

您可以使用命名函数表达式

MyApp.MyClass = function MyClass() { ... };

但请注意(惊喜)它们在所有版本的 IE 中都不能正常工作。

见: http: //kangax.github.com/nfe/

于 2012-08-23T10:54:10.220 回答
1

这不能回答问题

但是,该代码可能对其他人有用,因此我将其留在这里,以防万一。我不指望赞成票,但也请不要滥用它来反对票。谢谢。


我不知道您的用例,因此我认为您遇到了设计问题-您描述的问题在实践中不应该发生。

但是,假设您确实需要让这个工作。一个简单的方法来做你需要的事情是这样的:

function findNamed(obj, fn){
    for(var p in obj)
        if(obj[p] === fn)
            return p;
    return false;
}

var m = {};
m.MyClass = function() {};

console.log(findNamed(m, m.MyClass));

当然,解决方案可以做成更合适的 OOP 形式,但这只是提供一个想法。

要复制您的用例,它看起来像:

m.MyClass = function() {
    findNamed(this, arguments.callee);
};

所以,最终的代码是:

Object.prototype.getNameOfCall = function(fn) {
    for(var p in this)
        if(this[p] === fn)
            return p;
    throw "Callback not in object.";
};

var m = {};
m.MyClass = function() {
    console.log(this.getNameOfCall(arguments.callee)); // MyClass
};

m.MyClass(); // test it out
于 2012-08-23T11:01:07.830 回答