如何使用javascript原型在实例之间共享属性
How are properties shared across instances using javascript prototypes
我对原型继承的理解是每个对象都有一个原型属性。如果一个对象的属性不存在,那么它的原型对象就会被检查,以此类推。
在这个例子中,我的原型对象是一个带有counter属性的简单对象。
我希望每个实例共享相同的原型,但他们似乎得到了新的实例。这段代码的输出是00,我期望的是01。
我错过了什么明显的吗?
"use strict";
var ConstructorFunction = function () {};
ConstructorFunction.prototype = {
counter: 0,
count: function () {
return this.counter++;
}
};
var a = new ConstructorFunction();
var b = new ConstructorFunction();
$("#output").append(a.count());
$("#output").append(b.count());
这里是jsfiddle: http://jsfiddle.net/hdA6G/5/
原型属性在所有实例之间是共享的。问题是你永远不会改变原型属性。看看你的小提琴和一些额外的日志:
"use strict";
var ConstructorFunction = function () {};
ConstructorFunction.prototype = {
counter: 0,
count: function () {
return ++this.counter;
}
};
var a = new ConstructorFunction();
var b = new ConstructorFunction();
$("#output").append(a.hasOwnProperty("counter") + " "); //false
a.count();
$("#output").append(a.hasOwnProperty("counter") + " "); //true
如您所见,只要您调用++this.counter
,就会创建一个本地属性,并从该属性开始使用。
我假定是这样的:
++this.counter
解释为this.counter = this.counter + 1
。首先,计算等号右边的部分,因为实例没有counter
属性,所以使用原型的计数器属性。这个属性的值将被添加到1,然后分配给this.counter
,它现在创建一个本地属性,以同样的方式,当你分配一个根本不存在的属性时,比如a.xy = 1
。在这种情况下,xy
将是实例的本地属性。
编辑
有两种变通方法仍然可以让你使用prototype属性:1)在count
方法中显式地设置prototype属性:
ConstructorFunction.prototype.count = function() {
return ++this.constructor.prototype.counter;
};
2)使用apply
调用count方法,并使用原型作为上下文:
a.count.apply(a.constructor.prototype);
BUT,如果您按照您所做的方式设置prototype
属性,那么这两个方法都会出现问题。
ConstructorFunction.prototype = {
//...
};
这覆盖了整个原型对象,因此也覆盖了它的构造函数属性。构造函数属性现在将指向原型链中的下一个更高的对象,即Object
对象。要解决这个问题,您可以在分配原型对象后手动设置构造函数:
ConstructorFunction.prototype.constructor = ConstructorFunction;
或者单独分配原型对象的每个属性:
ConstructorFunction.prototype.counter = 0;
ConstructorFunction.prototype.count = function () {
return ++this.counter;
};
考虑使用闭包,这样你就可以将该变量保留为私有并在实例间共享:
var Class = (function ClassModule() {
var counter = 0;
function Class() {}
Class.prototype = {
count: function() {
return counter++;
}
};
return Class;
}());
var class1 = new Class();
var class2 = new Class();
console.log(class1.count()); //=> 0
console.log(class2.count()); //=> 1
counter
变量保存在闭包的上下文中(模块模式),并且不会在每个新实例中重复。
在基于原型的OOD中,共享意味着共享相同的定义并将其用于不同的上下文中。如果你需要一个静态属性在上下文之间共享,你可以按照下面的方法做
var ConstructorFunction = function (context) {
this.count = function () {
return context + "," + (++this.counter) + "," + (++ConstructorFunction.staticCounter);
};
};
ConstructorFunction.prototype.counter = 0;
ConstructorFunction.staticCounter = 0;
var context1 = new ConstructorFunction("context1");
var context2 = new ConstructorFunction("context2");
$("#output").append(context1.count());
$("#output").append(" ");
$("#output").append(context2.count());
http://jsfiddle.net/hdA6G/1/和更好的定义方式
var ConstructorFunction = function (context) {
this.context = context;
this.counter = 0;
};
ConstructorFunction.staticCounter = 0;
ConstructorFunction.prototype.count = function () {
return this.context + "," + (++this.counter) + "," + (++ConstructorFunction.staticCounter);
};
http://jsfiddle.net/hdA6G/3/你把继承弄反了,原型从基对象继承。我认为这更接近于你想要完成的目标。
function MyObject () {
this.count = 0;
};
ConstructorFunction.prototype = {
counter: function () {
return this.count++;
},
print: function () {
return this.count;
}
};
Var Foo = new MyObject();
console.log(Foo.counter()); // 1
console.log(Foo.counter()); // 2
console.log(Foo.print()); // 2
我希望这对你有帮助。
编辑
如果你想让你的计数器在所有实例中共享,那么它应该在你的基对象中。
function MyObject () {
this.count = 0;
this.counter = function () {
return this.count++; //may not need the this
}
};
我知道这是一个旧的帖子,但我是javascript的新手,在实验的时候我遇到了类似的东西,所以我想把我的2美分。
似乎每个对象在使用new
实例化后都得到了自己在prototype中声明的变量的副本。从那时起,使用this
访问将执行常规查找并找到要操作的私有副本。
试试这段代码。
var Worker = function (name) {
this.name = name;
}
Worker.prototype.jobs = 0;
Worker.prototype.Work = function () {
console.log("jobs finished", this.name, ++this.jobs);
}
Worker.prototype.WorkCount = function () {
console.log("work count", this.name, this.workCount);
}
var ca = new Worker("ca");
var cb = new Worker("cb");
ca.Work();// shows 1
cb.Work();// shows 1
ca.WorkCount();// shows undefined
cb.WorkCount();// shows undefined
Worker.prototype.workCount = 2;
ca.WorkCount();// shows 2
cb.WorkCount();// shows 2
- 在索引.html和应用.js [node.js] 之间共享变量
- Node.js上的WebSocket,并在所有连接的客户端之间共享消息
- 使用服务(AngularJS)在控制器之间共享数据
- AngularJS中的页面之间共享数据返回空
- 是否可以缓存可下载的文件,并在XHR和非XHR请求之间共享该缓存
- 在Knockoutjs中的ViewModels之间共享变量状态
- 通过共享服务在两个不同ng应用程序中的控制器之间共享数据
- Node.js服务器和浏览器之间共享二进制缓冲区
- 使用Angularjs在两个不同页面的控制器之间共享数据
- 在两个浏览器选项卡之间共享变量范围
- 不同进程之间共享Node.js环境
- 在Angular Bootstrap Modal和父控制器之间共享作用域
- 2ng控制器,并且需要在控制器之间共享数据
- Javascript创建函数,以便在其他函数之间共享变量
- 在控制器angular js之间共享数据
- 在javascript客户端和java服务器之间共享Google Analytics ClientID
- 如何将json文件中的数据提取到对象数组中,并在两个控制器之间共享
- Angular 2,在没有直接关系的两个组件之间共享一个对象
- 在angularJS中使用模态窗口时,在控制器之间共享对象数组
- 在角度上不同控制器之间共享状态