我一直在尝试在 javascript 中模拟静态属性。 在几个地方已经提到,class.prototype.property 在所有继承自该类的对象中都是静态的。但我的 POC 另有说法。请看一下:
使用 Class.prototype.property
//Employee class
function Employee() {
this.getCount = function(){
return this.count;
};
this.count += 1;
}
Employee.prototype.count = 3;
var emp = [], i;
for (i = 0; i < 3; i++) {
emp[i] = new Employee();
console.log("employee count is "+ emp[i].getCount());
}
/*Output is:
employee count is 4
employee count is 4
employee count is 4*/
我的问题 #1:如果这是静态的,那么 count 的值不应该是 4、5、6 等,因为所有对象都共享同一个 count 变量吗?
然后我用 Class.prototype 做了另一个 POC,我认为这是静态的。
使用 Class.property
//Employee class
function Employee() {
this.getCount = function(){
return Employee.count;
};
Employee.count++;
}
Employee.count = 3;
var emp = [], i;
for (i = 0; i < 3; i++) {
emp[i] = new Employee();
console.log("employee count is "+ emp[i].getCount());
}
/*Output is:
employee count is 4
employee count is 5
employee count is 6*/
我的问题 #2:我没有看到直接使用 class.property 的地方。 javascript 中的静态变量究竟是如何牢记我的上述代码的?
或者我在这里编码有误吗?这不是正确的认识吗?
最佳答案
My Question #1: If this were to be static, then shouldn't the value of count have been 4,5,6,etc as all the objects share the same count variable?
原型(prototype)属性在实例之间共享,但如果一个实例有自己的属性副本,它将使用它。分配给实例上的属性会为其提供自己的副本,因此它不再使用原型(prototype)。
+=、++ 和类似的运算符会导致赋值,因此它们也会导致此行为。
考虑:
function Employee() {
}
Employee.prototype.count = 0;
在上面的代码中,Employee.prototype 在内存中有一个对象。一些 ASCII 艺术:
+−−−−−−−−−−−−−−−−−−−−+ | Employee.prototype | +−−−−−−−−−−−−−−−−−−−−+ | count: 0 | +−−−−−−−−−−−−−−−−−−−−+
Then we do this:
var e = new Employee();
现在内存中有第二个对象,它有对 Employee.prototype 的引用:
+−−−−−−−−−−−−−−−+
| e |
+−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+
| [[Prototype]] |−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+
| count: 0 |
+−−−−−−−−−−−−−−−−−−−−+
And if you query e.count:
console.log(e.count);
...因为 e 没有自己的名为 count 的属性,引擎会查看 e 的原型(prototype)来找到它,找到它,并使用该值。
但是,当我们这样做时:
e.count += 1; // Or more idiomatically, `++e.count;` or `e.count++;`
分配一个值给 e 实例上的 count。 e 现在拥有 自己的 count 副本:
+−−−−−−−−−−−−−−−+
| e |
+−−−−−−−−−−−−−−−+
| count: 1 | +−−−−−−−−−−−−−−−−−−−−+
| [[Prototype]] |−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+
| count: 0 |
+−−−−−−−−−−−−−−−−−−−−+
Now if you query e.count:
console.log(e.count);
...引擎在 e 上找到 count,但不查看原型(prototype)。
你可以在代码中看到这个效果:
function Employee() {
}
Employee.prototype.count = 0;
var e = new Employee();
console.log(e.hasOwnProperty('count')); // false
e.count += 1;
console.log(e.hasOwnProperty('count')); // true
console.log(e.count); // 1
console.log(Employee.prototype.count); // 0
这也很有趣:
var e = new Employee();
console.log(e.count); // 0
++Employee.prototype.count;
console.log(e.count); // 1
由于e(还)没有它自己的count副本,如果我们实际增加Employee.prototype上的属性,无论是直接请求 (Employee.prototype.count) 还是间接请求 (e.count),我们都会看到更新后的值。
关于此的最后说明:如果 e 获得了自己的属性副本,您可以再次将其删除:
var e = new Employee();
console.log(e.count); // 0, because it's using `Employee.prototype.count`
++e.count; // Now `e` has its own `count` property
console.log(e.count); // 1, `e`'s own `count`
delete e.count; // Now `e` doesn't have a `count` property anymore
console.log(e.count); // 0, we're back to using `Employee.prototype.count`
delete 更恰本地称为 remove。它从对象中删除属性。
My Question #2: Nowhere I have seen class.property being used directly. How exactly are static variables made in javascript keeping in mind my above code?
两种方式:
正如您所做的那样,Employee.sharedProperty。
通过在函数内定义整个“类”,并在该函数内使用局部变量:
var Employee = (function() {
var sharedVariable = 0;
function Employee() {
++sharedVariable;
console.log("sharedVariable = " + sharedVariable);
}
return Employee;
})();
在该外部作用域函数中定义的所有函数都可以访问其中定义的局部变量。所以只有一个变量,即调用创建 Employee 的外部函数中的局部变量。
然后,这段代码:
new Employee();
new Employee();
new Employee();
new Employee();
输出
1 2 3 4
关于javascript:class.property 与 class.prototype.property 模拟静态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13486457/
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP
假设我有以下类(class):classPersondefinitialize(name,age)@name=name@age=ageenddefget_agereturn@ageendend我有一组Person对象。是否有一种简洁的、类似于Ruby的方法来获取最小(或最大)年龄的人?如何根据它对它们进行排序? 最佳答案 这样做会:people_array.min_by(&:get_age)people_array.max_by(&:get_age)people_array.sort_by(&:get_age)
我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,
假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl