使用Object的直接实例构造轻量级的字典

js对象的核心是一个字符串属性名与属性值的映射表。字典是可变长的字符串与值的映射集合。

js提供了枚举一个对象属性名的利器--for...in循环。

var dict={zhangsan:34,lisi:24,wangwu:62};
var people=[];
for(var name in dict){
  people.push(name+":"+dict[name]);
}
people;//["zhangsan:34", "lisi:24", "wangwu:62"]

使用自定义对象

但一些自定义的对象还会继承其原型对象中的属性,for...in循环除了枚举"自身"属性外,原型链中的属性也不会放过。

function NaiveDict(){ 
}
NaiveDict.prototype.count=function(){
  var i=0;
  for(var name in this){
     i++;
  }
  return i;
};
NaiveDict.prototype.toString=function(){
  return '[Object NaiveDict]';
};
var dict=new NaiveDict();
dict.zhangsan=24;
dict.lisi=34;
dict.wangwu=62;
dict.count();//5
上面的代码,实例化一个dict对象,并添加了私有属性(zhangsan,lisi,wangwu)并继承了原型对象的方法(toString,count),所以当调用count方法时,这个时候的for...in循环,不仅枚举了了私有属性也枚举了原型对象的方法属性(zhangsan,lisi,wangwu,toString,count)。

使用数组类型

利用js的灵活性,我们可以给任意的类型的对象添加属性,因此给数组添加属性似乎能工作。

var dict=new Array();
dict.zhangsan=24;
dict.lisi=34;
dict.wangwu=62;
dict.zhangsang;//24
当我们给数组的原型对象添加一些原型方法,这个时候我们再枚举上面的dict对象的属性时,错误就出现了。
Array.prototype.first=function(){
  return this[0];
};
Array.prototype.last=function(){
  return this[this.length-1];
};
Array.prototype.eq=function(idx){
  if(idx<0)idx=this.length+idx;
  return this[idx];
运行一下枚举
var names=[];
for(var name in dict){
  names.push(name);
}
names;//["zhangsan", "lisi", "wangwu","first","last"]

如何正确使用轻量级字典

要使用轻量级字典,最主要的是应该仅仅将Object的直接实例作为字典,而不是子类,或其它对象。
上面的数组的例子可以改成下面这些的代码

var dict={};
dict.zhangsan=24;
dict.lisi=34;
dict.wangwu=62;
dict.zhangsang;
var names=[];
for(var name in dict){
  names.push(name);
}
names;//["zhangsan", "lisi", "wangwu"]

使用轻量级字典的缺点:还是无法避免对于Object.prototype对象的修改,但可以将风险仅仅局限在Object.prototype。

优点:虽说所有人都可以修改Object.prototype对象,也会对for...in循环造成影响。但相比之下,增加属性到Array.prototype中是合理的。如之前给不支持数组标准方法的环境中将这些方法增加到Array.prototype中。这些属性也会导致for...in循环,坚持Object的直接实例原则,可以使得for...in循环摆脱原型污染的影响。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的使用轻量级锁的示例代码: ```java public class LightLockExample { private int count; private volatile Object lock = new Object(); public void increment() { synchronized (lock) { count++; } } public void incrementWithLightLock() { // 尝试获取轻量级锁 if (compareAndSetLock()) { try { count++; } finally { // 释放轻量级锁 unlock(); } } else { // 获取轻量级锁失败,使用重量级锁 synchronized (lock) { count++; } } } private boolean compareAndSetLock() { // 使用CAS操作尝试获取轻量级锁 return unsafe.compareAndSwapObject(this, lockOffset, null, Thread.currentThread()); } private void unlock() { // 将锁的持有者设置为null,释放轻量级锁 unsafe.putObjectVolatile(this, lockOffset, null); } private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); private static final long lockOffset; static { try { lockOffset = unsafe.objectFieldOffset(LightLockExample.class.getDeclaredField("lock")); } catch (Exception ex) { throw new Error(ex); } } } ``` 该示例中,使用了一个Object类型的锁对象lock来保证线程安全。在incrementWithLightLock方法中,首先尝试使用compareAndSetLock方法获取轻量级锁,如果成功,则执行count++操作,并在finally块中释放轻量级锁;如果失败,则使用重量级锁来保证线程安全。 compareAndSetLock方法使用了Unsafe类的compareAndSwapObject方法来进行CAS操作,尝试将lock对象的值从null修改为当前线程,如果修改成功,则获取轻量级锁;如果修改失败,则说明其他线程已经获取了轻量级锁,当前线程需要使用重量级锁来保证线程安全。 在unlock方法中,使用了Unsafe类的putObjectVolatile方法来将锁的持有者设置为null,释放轻量级锁。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值