2011-08-09 100 views

回答

16

你说得对,JavaScript没有类(但是),但它确实有构造函数,定义了对象和构造函数之间关系的instanceof运算符,以及基于原型链的继承形式。

obj instanceof ctorctor.prototypeobj的原型链上时为true。

模下方的警告,你可以在5的EcmaScript实施instanceof从而

function isInstanceOf(obj, ctor) { 
    var proto = ctor.prototype; 
    if (typeof obj === "object" || typeof obj === "function") { 
    while (obj) { 
     if (obj === proto) { return true; } 
     obj = Object.getPrototypeOf(obj); 
    } 
    } 
    return false; 
} 

除非你去重新分配各地的原型(o = new MyConstructor(); MyConstructor.prototype = somethingElse)应该是这样的情况new MyConstructor() instanceof MyConstructor

15.3.5.3部分对此进行了详细解释。

15.3.5.3 [[HasInstance]] (V)

假设F是一个功能对象。

当F的[[HasInstance]]内部方法被调用,值V,采取以下步骤:

  1. 如果V不是一个对象,返回false。
  2. 设O是调用属性名称为“prototype”的F的[[Get]]内部方法的结果。
  3. 如果Type(O)不是Object,则抛出TypeError异常。
  4. 重复

    1. 令V的[[原型]]五
    2. 如果V是空的内部属性,返回false值。
    3. 如果O和V引用同一个对象,则返回true。

因为主机对象(如DOM节点)被允许执行[[HasInstance]]内部方法但他们喜欢,但大多数浏览器采用主机对象为行为密切本地对象这并不是故事的全部尽可能。

+0

不要说'(还)':(类仍然是strawman。如果我们很幸运,他们不会进入ES6! – Raynos

-2

Javascript是面向对象的,所以它确实有类。根本没有明确的“class”指令,就像你在其他OOP语言中那样。

+4

Javascript没有类,它是ap基于轮转的语言,这是一种实现面向对象的不同方式。差异可能很微妙,但它们很重要。 –

5

JavaScript并没有类,但它确实有类型。您可以定义自己的类型和使用new关键字创建新实例:

function Foo(initialValue) { 
    this.value = initialValue || 0; 
} 
var foo = new Foo(17); 
var fooIsAFoo = foo instanceof Foo; // true! 
var fooIsAnObject = foo instanceof Object; // also true! We have inheritance here :) 
+0

你可以通过引用规范来支持'Types'的概念吗?我有一种感觉,只有本地类型,'Foo'不是一种类型。 – Raynos

1

JavaScript不使用经典的继承,它采用prototypal inheritance这里的一切是一个“对象”,并继承是通过克隆来完成,例如:

var myPrototype = function() { 
    var privateMember = "I am private"; 
    var publicMember = "I am public"; 
    var publicMethod = function() { 
     alert(privateMember); 
    } 
    return { 
     publicMember = publicMember, 
     publicMethod = publicMethod 
    } 
} 

var myInstace = new myPrototype(); 
myInstance.publicMethod(); 

这里myInstance可以说是一个myPrototype“的情况下”,但在现实中所发生的事情是利用你克隆myPrototypenew关键字来创建myInstance

3

在JS中,函数是一个对象。这需要一段时间才能习惯,但这是事实。把这个放在一边,你看别人使用的代码会更有意义。如果你已经看到Javascript在人们将函数(){}作为参数传递给另一个函数的情况,那就证明函数是第一类对象。 (你花了我一段时间),那么你需要明白,如果你做了一个函数,你可以得到它的一个新实例。请参阅以下代码:

function FooName(){ 
    var name; 
    this.setName = function(n){ 
     this.name = n; 
    } 
    this.getName = function(){ 
     return this.name; 
    } 
} 
var n1 = new FooName(); 
var n2 = new FooName(); 
n1.setName("FOO"); 
n2.setName("BAR"); 

此时,您有两个FooName方法实例:n1和n2。在JS中用一个大写的第一个字母来命名实例化函数是一种惯例,而不是客户小写的第一个字母。在这个例子中,我指出我的函数可以通过将它命名为FooName而不是fooName来实例化。我希望这是有道理的。

在上面的例子中,n1有三个属性。私有名称属性,公共setName属性和公共getName属性。每次我实例化一个新的FooName时,都会创建一个getName和setName的副本。这可能浪费内存空间。由于getName和setName不会改变,我不需要每个FooName实例的新副本。这是原型进来的地方。

你可以这样说,然后getName和setName只会在内存中存在一次,从而释放内存,这是一件好事。

FooName.prototype.setName = function(n){ 
    this.name = n; 
} 
FooName.prototype.getName = function(){ 
    return this.name; 
} 

如果从FooName功能删除的getName和setName,那么现在你将有一个FooName“类”有两种方法,的getName和setName。

玩它。如果您有任何问题,请告诉我。

+0

不知道这是否回答@ loldrup的问题,但它确实给了我一些见解。谢谢+1 – brenjt

+0

True ... 我想我会说“instanceof”意味着你有一个函数,并且已经声明了一个新的函数。关键词“新”是什么让你的实例。例如,我的代码如上,var n3 = FooName与var n3 = new FooName不一样。离开新的区别非常显着。如果你离开了“新”,那么单词“this”的所有用法都会指向窗口本身。 JS中的“this”是指它被调用的上下文。如果你在一个obj实例中调用它,它会引用obj。如果你在obj实例外面调用它,它是全局的。 – frosty

+1

“如果您从FooName函数中删除getName和setName,那么现在您将拥有一个FooName”class“,它具有两个方法getName和setName。” 也就是说,(函数 - ) - 对象FooName的原型对象现在具有这些函数,并且由于能够遵循原型链的名称解析方法,FooName的所有实例都能够找到这些方法。这是你的意思吗? – loldrup