使用';原型&x27;与';这';用JavaScript?
两者之间有什么区别使用';原型&x27;与';这';用JavaScript?,javascript,prototype,this,Javascript,Prototype,This,两者之间有什么区别 var A = function () { this.x = function () { //do something }; }; 及 第一个示例仅更改该对象的接口。第二个示例更改了该类所有对象的接口。在大多数情况下,它们基本相同,但第二个版本节省了内存,因为每个对象只有一个函数实例,而不是单独的函数 使用第一个表单的原因是访问“私人成员”。例如: var A = function () { var private_var = ...
var A = function () {
this.x = function () {
//do something
};
};
及
第一个示例仅更改该对象的接口。第二个示例更改了该类所有对象的接口。在大多数情况下,它们基本相同,但第二个版本节省了内存,因为每个对象只有一个函数实例,而不是单独的函数 使用第一个表单的原因是访问“私人成员”。例如:
var A = function () {
var private_var = ...;
this.x = function () {
return private_var;
};
this.setX = function (new_x) {
private_var = new_x;
};
};
由于javascript的作用域规则,private_var可用于分配给此.x的函数,但不能用于对象之外。我相信@Matthew Crumley是正确的。它们在功能上(如果不是结构上)是等价的。如果使用Firebug查看使用
new
创建的对象,可以看到它们是相同的。然而,我的偏好如下。我猜这更像是我在C#/Java中所习惯的。也就是说,定义类、定义字段、构造函数和方法
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDIT并不意味着变量的作用域是私有的,我只是想说明如何用javascript定义我的类。变量名称已更改以反映这一点。示例的结果非常不同 在查看差异之前,应注意以下几点:
- 构造函数的原型提供了一种通过实例的私有
属性在实例之间共享方法和值的方法[[prototype]]
- 函数的这一属性是通过调用函数的方式或通过使用bind(此处未讨论)来设置的。如果在对象上调用函数(例如
),则该方法中的函数引用该对象。如果这不是通过调用或使用bind设置的,则默认为全局对象(浏览器中的窗口)或在严格模式下保持未定义状态myObj.method()
- JavaScript是一种面向对象的语言,即大多数值都是对象,包括函数。(字符串、数字和布尔值不是对象。)
var A = function () {
this.x = function () {
//do something
};
};
在这种情况下,变量A
被分配一个值,该值是对函数的引用。使用A()
调用该函数时,函数的this不是由调用设置的,因此它默认为全局对象,表达式this.x
有效window.x
。结果是,对右侧函数表达式的引用被指定给window.x
在下列情况下:
var A = function () { };
A.prototype.x = function () {
//do something
};
发生了完全不同的事情。在第一行中,变量A
被分配一个函数的引用。在JavaScript中,默认情况下,所有函数对象都有一个prototype属性,因此没有单独的代码来创建a.prototype对象
在第二行中,A.prototype.x被指定一个函数的引用。如果x属性不存在,这将创建一个x属性;如果存在,则将指定一个新值。因此,与第一个示例不同的是,在该示例中,表达式中涉及对象的x属性
另一个例子如下。这与第一个类似(也许还有你想问的问题):
在本例中,在函数表达式之前添加了new
运算符,以便将函数作为构造函数调用。使用new
调用时,函数的this设置为引用一个新对象,该对象的私有[[Prototype]]
属性设置为引用构造函数的公共原型。因此,在赋值语句中,将在此新对象上创建x
属性。当作为构造函数调用时,函数默认返回其this对象,因此不需要单独的返回this代码>语句
要检查A是否具有x属性,请执行以下操作:
console.log(A.x) // function () {
// //do something
// };
这是new的一种不常见用法,因为引用构造函数的唯一方法是通过.constructor。更常见的做法是:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
实现类似结果的另一种方法是使用立即调用的函数表达式:
var A = (function () {
this.x = function () {
//do something
};
}());
在这种情况下,A
分配了调用右侧函数的返回值。这里再次说明,由于调用中未设置此项,因此它将引用全局对象,并且此.x
有效窗口.x
。由于函数不返回任何内容,A
的值为undefined
如果将Javascript对象序列化到JSON或从JSON中反序列化,这两种方法之间的差异也会表现出来。序列化对象时,对象原型上定义的方法不会序列化,例如,当您只想序列化对象的数据部分,而不想序列化对象的方法时,这会很方便:
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
相关问题:
旁注:这两种方法之间可能没有任何显著的内存节省,但是使用原型共享方法和属性可能比每个拥有自己副本的实例使用更少的内存
JavaScript不是低级语言。将原型设计或其他继承模式视为显式更改内存分配方式的一种方式可能不是很有价值。正如其他人所说,第一个版本使用“this”会导致类a的每个实例都有自己的函数方法“x”的独立副本。而使用“prototype”将意味着类A的每个实例将使用方法“x”的相同副本
下面是一些代码来显示这一细微差别:
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
正如其他人提到的,选择一种或另一种方法有各种原因。我的示例只是为了清楚地演示差异。原型是类的模板;这适用于它的所有未来实例。然而,这是对象的特定实例。最终的pr
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
var A = function() { this.hey = function() { alert('from A') } };
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined
var a1 = new A();
a1.__proto__ = A.prototype;
A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}
var A = function() { this.hey = function() { alert('from A') } };
a1.hey = function() { alert('from A') }
var a2 = new A();
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
a1.hey
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor