js for in 和for区别详解

在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的,我们应该清楚什么是枚举属性,什么是不可枚举属性?

1.怎么判断属性是否可枚举

一.propertyIsEnumerable方法
每个对象都有一个 propertyIsEnumerable 方法。此方法可以确定对象中指定的属性是否可以被枚举,但是通过原型链继承的属性除外。如果对象没有指定的属性,则此方法返回 false,propertyIsEnumerable() 方法返回一个布尔值,表示指定的属性是否可枚举。

var  arr = [1,2,3,4];
 Array.prototype.method  = function(){
     console.log("method");
 };
 console.log(arr.propertyIsEnumerable(0));//true  arr[0]===1
 console.log(Array.prototype.propertyIsEnumerable("method"));//true
 console.log(Array.prototype.propertyIsEnumerable("concat"));//flase

二.Object.getOwnPropertyDescriptor方法
返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

var  arr = [1,2,3,4];
Array.prototype.method  = function(){
 console.log("method");
};
console.log(Object.getOwnPropertyDescriptor(arr,0)); //{value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(Array.prototype,"method"));//{value: ƒ, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(Array.prototype,"split"));//{value: ƒ, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(Array.prototype,"concat"));//{value: ƒ, writable: true, enumerable: false, configurable: true}

主要是enumerable这个属性来决定是否可枚举!
1.value:代表该属性的值
2.writable :当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)
3.enumerable:当且仅当指定对象的属性可以被枚举出时,为 true
4.configurable:当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。

2.修改是否可枚举

Object.defineProperty方法(直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象)

var  arr = [1,2,3,4];
Array.prototype.method  = function(){
    console.log("method");
};
Object.defineProperty(Array.prototype,"method",{
   enumerable:false
})
console.log(Array.prototype.propertyIsEnumerable("method"));//false
3.对比循环

有了上面的了解,我们再来说说 for in 和for循环的吧

一.for…in 循环只遍历可枚举属性(包括它的原型链上的可枚举属性)
它会把原型链上的属性遍历出来,不过你可以通过hasOwnProperty过滤掉!for循环不会遍历出原型链上的属性!

 var  arr = [1,2,3,4];
 Array.prototype.method  = function(){
     console.log("method");
 };
 for(var k  in arr){
     console.log(arr[k]);//1,2,3,4,ƒ (){console.log("method");}
 };
 for(var k  in arr){
     if(arr.hasOwnProperty(k)){
        console.log(arr[k]);//1,2,3,4
     };
 };
 //看下for循环
for(var i =0 ;i<arr.length;i++){
    console.log(arr[i]);//1,2,3,4
}

二.for…in和for遍历数组时下标类型不一样

var  arr = [1,2,3,4];
  for(var k  in arr){
      if(arr.hasOwnProperty(k)){
         console.log(typeof k);//string
      };
  };

  for(var i =0 ;i<arr.length;i++){
      console.log(typeof i); //number
  }

for in 的下标是string,for下标是number,这点比较容易忽略!
三.对稀疏数组的执行效率
什么是稀疏呢?稀疏也就是说,数组中的元素之间可以有空隙!

var  arr = [1,2,3,4];
arr.length =10;
console.log(arr); //这个就是稀疏数组 [1, 2, 3, 4, empty × 6]

再来看下执行效率

var arr = [1, 2, 3, 4];
arr.length = 10;
console.log(arr);
for (var k in arr) {
    if (arr.hasOwnProperty(k)) {
        console.log(k); //0,1,2,3
    };
};

for (var i = 0; i < arr.length; i++) {
    console.log(i); //0,1,2,3,4,5,6,7,8,9
}

我们知道如果将其length属性设置为大于数组项数的值,其实后面多出的每一项都会是undefined值,for in 只执行4次,而for循环执行了10次,

console.log(arr.propertyIsEnumerable(3));//true
console.log(arr.propertyIsEnumerable(4));//false
console.log(arr.propertyIsEnumerable(5));//false
console.log(arr.propertyIsEnumerable(6));//false
console.log(arr.propertyIsEnumerable(7));//false
console.log(arr.propertyIsEnumerable(8));//false
console.log(arr.propertyIsEnumerable(9));//false
console.log(arr.propertyIsEnumerable(10));//false

这个就是为什么for in 只执行4次,因为for in 对于不存在的项是不会被枚举出来的!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值