0

我不确定如何问这个问题,所以我会举个例子。说我有这个设置:

var x = function() {
  console.log('YAY!');
};
x.test0 = 0;
x.test1 = 1;
x.test2 = "hello world";

按预期工作:

x(); // YAY!
x.test0 // 0
x.test2 // "hello world"

现在,我想知道如何首先从一个对象开始设置它。我尝试使用构造函数添加函数,但这不起作用。

var x = {
  test0 : 0,
  test1 : 1, 
  test2 : 'hello world',
  constructor: function() {
    console.log('YAY!');
  }
}

x(); // object is not a function
x.test0 // 0
x.test2 // "hello world";

我尝试过其他疯狂的事情,但似乎没有任何效果。

有任何想法吗?还是我坚持第一种方式?

4

4 回答 4

3

如您的第一个示例所示,JavaScript 中的函数是对象并且可以具有属性。

ECMAScript 为对象定义了“内部属性”(和内部方法)。这些内部属性有助于定义对象的状态,但并非所有对象的内部属性都可以直接从代码中设置。我们用双方括号表示内部属性名称,例如[[Foo]].

当您调用类似的函数时foo(),您将运行对象的[[Call]]内部方法。但是,只有函数对象有[[Call]]内部方法。无法设置或更改非宿主对象的[[Call]]方法;它是在定义对象时设置的,ECMAScript 没有定义机制来更改它。(“主机”对象是浏览器或其他执行环境提供的对象,可以按不同的规则播放。除非您正在编写浏览器,否则您可能不需要考虑这个例外。)

因此,如果您定义一个函数

foo = function() { doStuff(); return 5; };

该函数(分配给变量foo)有一个永久方法(根据第 13.2 节[[Call]]中的函数创建规则),该方法运行并返回。doStuff5

如果你有一个非函数对象

foo = { };

该对象缺少[[Call]]属性。没有办法给它一个[[Call]]属性,因为非宿主对象只能[[Call]]在定义时设置。逻辑内部属性[[Call]]不对应于实际代码中可访问的任何对象属性。

总之,使非函数对象可调用是不可能的。如果您希望一个对象是可调用的,请首先将其定义为一个函数,就像您在第一个示例中所做的那样。

于 2013-10-03T18:15:41.647 回答
1

简单地说,你不能。为什么?因为两个对象的类型不同,第一个 aFunction Object和第二个返回一个标准对象。所以两者都继承自不同的祖先。这里唯一的可能性是,如果您可以将对象转换为函数,并且 JavaScript 本身没有这样的东西可用。但是,您可以使用自己的 cast 方法。

function toFunction (obj, fnProp) {
    var fn = function () {};
    if (typeof obj[fnProp] !== 'function') return fn;
    else {
        fn = obj[fnProp];
        for (prop in obj) {
            fn[prop] = obj[prop];
        }
    }
    return fn;  
}


var z = toFunction(y, 'prototype');    // with your example
于 2013-10-03T18:38:54.677 回答
0

你不能只是创建一个对象,然后像函数一样运行它。

你可以反过来做,因为在 JavaScript 中,函数是一个对象:

x.prop=1;
console.log(x.prop);

function x() {
    return true;
}
于 2013-10-03T17:15:45.340 回答
0

没有得到你想要的东西,你想要面向对象的东西吗?这可能会有所帮助

function x(){
    this.test0 = 0;
    this.test1 = 1;
    this.test2 = 'hello word';
    console.log('Wow!');
}

var y = new x(); // new object of x PRINTS WOW and set's default values
console.log(y.test0) // 0
console.log(y.test2) // "hello world";
于 2013-10-03T17:25:22.663 回答