什么'是Javascript中的'实例'?

时间:2011-08-09 20:25:58

标签: javascript function object instance

这个问题的答案: What is the initial value of a JavaScript function's prototype property?

有这句话:

  

任何新创建的Function实例的prototype的初始值是Object

的新实例

据我所知,Javascript没有类,因此“实例”这个词在我脑海中没有意义。如何解释Javascript中的“实例”?

抱歉,我没有足够的代表将我的问题放在答案的评论主题中。

7 个答案:

答案 0 :(得分:16)

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

obj instanceof ctor位于ctor.prototype原型链上时,

obj为真。

如下所示,您可以在EcmaScript 5中实现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是一个Function对象。

     

当使用值V调用F的[[HasInstance]]内部方法时,将执行以下步骤:

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

         
        
    1. 设V为V的[[Prototype]]内部属性的值。
    2.   
    3. 如果V为null,则返回false。
    4.   
    5. 如果O和V引用同一个对象,则返回true。
    6.   
  8.   

这不是全部故事,因为允许主机对象(如DOM节点)实现[[HasInstance]]内部方法,但他们喜欢但大多数浏览器实现主机对象的行为与本机对象尽可能接近。 / p>

答案 1 :(得分: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 :)

答案 2 :(得分:3)

在JS中,函数是一个Object。需要一段时间才能适应这种情况,但事实确实如此。把它扔了一会儿,你看到别人使用的代码会更有意义。如果您已经看到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“class”,它有两个方法,getName和setName。

玩它。如果您有疑问,请告诉我。

答案 3 :(得分:1)

在JavaScript函数中是第一类对象,这意味着你可以像对待任何对象一样处理它们。

//定义类

   function User(name,age)
    {
        this.Name=name;
        this.Age=age
    }

//创建insatnces

var user1= new User('Demo1','50');
var user2= new User('Demo2','100');


alert(user1.Name);
alert(user2.Name);

http://jsfiddle.net/praveen_prasad/hmUku/

http://en.wikipedia.org/wiki/First-class_function

答案 4 :(得分: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可以说是“{1}}的”实例“,但实际上发生的事情是使用您克隆的myPrototype关键字new来创建{ {1}}。

答案 5 :(得分:0)

所以现在我已经捏造了一个描述我认为你们所有人*的话的页面: https://docs.google.com/document/d/1VvqqO2LMmilLbIvcU2JHI9ifaoMs-DB-farEzwuVuwM/edit?hl=da

用漂亮的图形说明:)

对待Jon

*和此链接: http://trephine.org/t/index.php?title=Understanding_the_JavaScript_new_keyword

答案 6 :(得分:-2)

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