简体   繁体   English

javascript中的构造函数和原型

[英]Constructor and prototype in javascript

What is the difference between this two codes and which one should I use? 这两个代码有什么区别,我应该使用哪一个?

function Test() {}
Test.method = function() {};

With Prototype: 使用Prototype:

function Test() {}
Test.prototype.method = function() {};

1st case : static method. 第一种情况:静态方法。

function Test() {}
Test.method = function () { alert(1); };
var t = new Test;
Test.method(); // alerts "1"
t.method(); // TypeError: Object #<Test> has no method 'method'

2nd case : instance method. 第二种情况:实例方法。

function Test() {}
Test.prototype.method = function () { alert(1); };
var t1 = new Test;
var t2 = new Test;
t1.method(); // alerts "1"
t2.method(); // alerts "1"
Test.method(); // TypeError: Object function Test() {} has no method 'method'

The first example merely assigns a function to a new property of Test called method . 第一个例子只是将一个函数赋给Test一个新属性called method There is nothing special or magic about it (by which I mean, the language does not do anything interesting with it). 关于它没有什么特别的或神奇的(我的意思是,语言不会对它做任何有趣的事情)。 You might call this a static method, because it's shared across all instances, but it's really just a normal property. 您可以将其称为静态方法,因为它在所有实例中共享,但它实际上只是一个普通的属性。 (Functions are objects and objects have properties.) (函数是对象,对象具有属性。)

In the second case, a new method is added to Test 's prototype , which makes it available to all instances of Test . 在第二种情况下,为Testprototype添加了一个新方法,使其可用于所有Test 实例 This is special behavior. 特殊行为。 Every object in JavaScript has an internal link to another object, which is called its prototype. JavaScript中的每个对象都有一个指向另一个对象的内部链接,称为原型。 This link is established using the prototype of the constructor that created the object, so any instance created by Test will have the new property in its prototype chain. 此链接是使用创建对象的构造函数的prototype建立的,因此Test创建的任何实例都将在其原型链中具有新属性。

For example: 例如:

function Test() {}
Test.method = function() {};

var a = new Test();
console.log(a.method); // => undefined

But: 但:

function Test() {} 
Test.prototype.method = function() {};

var a = new Test();
console.log(a.method); // => function

原型方法在所有Test实例之间共享。

Will NOT Work (for an instance) 不会工作(例如)

function Test() {}
Test.method = function() {};

Will Work (for an instance) 将工作(例如)

function Test() {}
Test.prototype.method = function() {};

Why? 为什么?

Assuming that you create an instance of Test: 假设您创建了一个Test实例:

t = new Test()

On calling a method: 在调用方法时:

t.method()

JavaScript will first look within Test, for example the 3 properties and methods will be recognized below: JavaScript将首先在Test中查看,例如,下面将识别3个属性和方法:

function Test() {} {

    this.a = "hello";
    this.b = "world";
    this.c = function() { alert( this.a + this.b) }

}

and then the second , the look up will be done on prototype: 然后第二个 ,查找将在原型上完成:

Test.prototype.method = function() { console.log('prototype defined method') }

In JavaScript the below does not register to the instance t but instead Test : 在JavaScript中,下面没有注册到实例t ,而是Test

Test.method = function() { console.log('something unsual') };

therefore 因此

Test.method()  // works
t.method()     // no works

The difference goes back to how the prototype chaining works. 差异可以追溯到原型链的工作原理。 If you create instances of Test then they will be able to access the methods that are defined on the prototype. 如果您创建Test实例,那么他们将能够访问原型上定义的方法。

The first code, simply adds a "static" method on the constructor; 第一个代码,只是在构造函数上添加一个“静态”方法; You won't be able to access that method doing something like this: 您将无法访问该方法,执行以下操作:

var testInst = new Test();
testInst.method() // Error Undefined is not a function

The only way to invoke that method is via the constructor reference ie 调用该方法的唯一方法是通过构造函数引用ie

Test.method();

As i mentioned, the above is feasible if you add the method to the prototype of the constructor. 正如我所提到的,如果将方法添加到构造函数的原型中,则上述操作是可行的。

If you define a method in the prototype, any instances will be able to use that method. 如果在原型中定义方法,则任何实例都可以使用该方法。 If you define the method as simply a part of the original object, it allows you to simply use that in a manner that one could reasonably refer to as a static method. 如果将方法定义为原始对象的一部分,则允许您以可合理地称为静态方法的方式使用该方法。

For example: 例如:

Array.isArray( [] )  //true

[].isArray() //throws a TypeError

The second example throws a TypeError because isArray() is not in the Array.prototype (remember, instances only access methods defined in that instance, or in that instance's prototype or __proto__ chain). 第二个示例抛出一个TypeError因为isArray()不在Array.prototype (请记住,实例只访问在该实例中定义的方法,或者在该实例的prototype__proto__链中)。

In short: 简而言之:
* A method defined in the original object can be accessed by that object, but not instances of that object. *原始对象中定义的方法可以由该对象访问,但不能访问该对象的实例。
* A method defined in the original object's prototype can be accessed by any instance of the original object. *原始对象的原型中定义的方法可以由原始对象的任何实例访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM