5

这个问题更多的是关于支持和向后兼容性。我已经测试了以下代码。

function newFunc() {}

newFunc.prototype = {

    literal : {
        init : function() {
            console.log(this);
            this.test();
        },
        test : function() {
            console.log('test');
        }
    }
}

var inst = new newFunc();

inst.literal.init();

虽然我没有在任何其他代码中看到对象文字作为原型,但这很有效。是否有一个原因?这对我来说似乎是一种合乎逻辑的编码方式,但如果它有严重的陷阱,我不想追求它。

4

4 回答 4

2

使用对象字面量为函数创建原型是完全正常的,但通常仅作为对象的实际prototype

不寻常的是做你所做的并在原型中包含一个嵌套对象。

实际上,您只向原型添加了一个对象,名为literal. 所有的方法都是该对象的属性。它在技术上是有效的语法,但我以前从未见过它使用过。正如@squint 在评论中指出的那样,它似乎也破坏了this变量的工作方式,因为它绑定this到函数调用中使用的“next left”属性:

var inst = new newFunc();
inst.literal.init();
> Object { init: function, test: function }

iethis已设置为指向.literal对象,而不是已创建的实际实例。

于 2013-05-29T13:47:08.197 回答
1

Yes, using literals for prototype is correct. For example Mozilla explicitly uses a literal in the prototype's documentation:

var Customer = function(name) {
    this.name = name;
}

var Person = { // this is a literal
    canTalk : true,
    greet : function() { /* ... */ }
}

Customer.prototype = Person;

Some explanation: Value of prototype is an object. It doesn't matter how the object was created - using simply {} is fine. It is often initialized using something like MyClass1.prototype = new MyClass2(), but new just creates a new object. It also sets the prototype property and executes the constructor (MyClass2) but on the new object, it doesn't affect MyClass1 in any way (see explanation here).

Using a nested literal doesn't make a difference. In the question, the prototype is set to { literal : { ... } }. What actually happens when you call inst.literal.init() is:

  1. The runtime looks at inst and checks whether the object has a value assigned for property literal.
  2. inst dos not have such property, therefore the runtime continues with its prototype property
  3. inst.prototype references the literal object to which it was initialized. This object has assigned a value for property literal.
  4. inst.literal therefore evaluates to the nested literal inst.prototype.literal
  5. The literal object does have a value for property init
  6. The init() function is called

This is one of the principles of JavaScript (ECMA Script) so there should be no compatibility issues.

于 2013-05-29T13:38:02.147 回答
0

您正在做的是将原型设置为具有多个属性的 JavaScript 对象。这是完全可以接受的,因为函数的行为与 JavaScript 中的对象非常相似。JavaScript 所做的只是将对该原型属性的引用传递给继承的对象,因此在这种情况下,它们将没有可以访问的函数,而是一个对象。

您可以看到这实际上是在 MDN 文档中完成的:

var Person = {
    canTalk : true,
    greet : function() {
        if (this.canTalk) {
            console.log("Hi, I'm "+this.name)
        }
    }
}
Customer.prototype = Person;

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fprototype

于 2013-05-29T13:35:58.453 回答
-1

如果我理解正确,他们说你可以在 javascript (ECMA SCRIPT) 中做到这一点

http://en.wikipedia.org/wiki/Literal_(computer_programming)

但我知道的是,如果你想实例化你的对象,旧浏览器会出现问题。你不能用 Object.create() 函数实例化对象

所以你通常应该这样做......

var foo = function(){};
foo.prototype = {func:function(){}}
var bar = new foo();

就像你这样做或那样:)

于 2013-05-29T13:24:18.710 回答