2个JavaScript对象有什么区别?

时间:2011-03-22 08:31:35

标签: javascript javascript-framework

我尝试提高我的JavaScript技能。 我不明白为什么(5)有效,(2)返回错误。不一样吗?

  1. B.fn()//确定
  2. B.fn2()// TypeError:Object#没有方法'fn2'
  3. var a = new A()
  4. a.fn()//确定
  5. a.fn2()//确定

    var A = function () {
        this.fn = function () { alert(3); }
    }
    A.prototype = {
        fn2: function () { alert(4); }
    };
    
    var B =
        {
            fn: function () { alert(1); }
        }
    B.prototype = {
        fn2: function () { alert(2); }
    };
    

4 个答案:

答案 0 :(得分:7)

aA类的一个实例,其中B是类本身。由于fn2未定义为静态函数,因此它仅对类B的实例可用,而不是类B本身。

如果您想直接使用B,可以使用:

new B().fn2()

如果您将B定义为function()

或者,您可以按照定义fn2

的方式定义fn

答案 1 :(得分:1)

(简单解释) prototype属性仅在使用function作为构造函数时使用(通过使用new运算符)。 function创建了prototype的克隆,并将函数内的this关键字设置为克隆。克隆上的属性是prototypes属性的直接引用/指针。

对象文字{}是替代new Object()的更强大的表达式,因此从Object.prototype“继承”属性。

所以:

function ClassLike() {}
ClassLike.prototype = {
    foo : "bar"
}

var instance = new ClassLike();
alert( instance.foo ); // bar

可行,因为new运算符会动态执行某些操作来创建新对象,而不是:

var instance = {
    foo : "bar"
}
instance.prototype = {
    baz : "foobar"
}

仅为已创建的对象添加另一个属性(原型),并且没有任何进程可以实际分配/更改对象原始原型。

现在,Mozilla已经添加了一个非标准(IE不支持它)的方式来通过__proto__更改已经实例化的对象原型,并且有一些请求将它添加到ES5(EcmaScript 5)。我不会用它来运行。但它的工作原理如下:

var instance = {};
var parent = {
    foo : "bar"
}
instance.__proto__ = parent;

alert( instance.foo ); // bar

更改已经实例化的对象原型的另一种方法是添加到Object构造函数原型(由于多种原因不建议)。就这样:

var instance = {}; // a more powerful alternative to `new Object()`

Object.prototype.foo = "bar";

alert( instance.foo ); // bar

这一切都是可能的,但这样做是明智的......我会说不,但意见各不相同,我宁愿避免辩论;)

无论如何,只要记住prototype属性在您new function时有用,否则它只会成为实例上的属性。

答案 2 :(得分:0)

你所演示的内容是由我认为是JavaScript中OO的最大问题引起的:原型必须是构造函数的属性而不是对象本身。这意味着如果你有一个可以很容易地定义为对象文字的对象,你仍然需要一个无用的构造函数来定义你的对象的原型。

阅读本文:道格拉斯克罗克福德的Prototypal Inheritance in JavaScript。以下是相关部分:

  

[...] JavaScript本身存在冲突   关于它的原型性质。在一个   原型系统,对象继承   来自物体。然而,JavaScript,   缺乏执行该操作的操作员   操作。取而代之的是new   运算符,new f()生成的运算符   一个继承自的新对象   f.prototype这种间接是   旨在使语言看起来   对经典训练更为熟悉   程序员,但未能做到这一点,因为   我们可以从非常低的意见看出来   Java程序员拥有JavaScript。   JavaScript的构造函数模式确实如此   不吸引古典人群。它   也掩盖了JavaScript的真实性   原型性质。结果,那里   是很少有程序员知道如何   有效地使用该语言。   幸运的是,很容易创建一个   实现true的运算符   原型继承。它是一个   我的工具包中的标准功能,我   强烈推荐给你。

阅读文章,了解一些想法,而不是如何有效地解决你想要做的事情。

答案 3 :(得分:0)

嗯,你的答案很简单。在JavaScript中,只有构造函数有“原型”,即原型属性。对象文字,例如“{}”不。因此,除非您按如下方式更改,否则您的2号将永远不会起作用:

var B = function(){ // the B constructor
          return this;
        }
B.prototype = {
fn2: function(){ alert(2); }
}