对象的深入理解

对象作为六种基本类型的一种,在js中是非常常用的。但是还有许多关于对象的深入的知识了解不深。在这里总结一下关于对象的知识。

对象类型

JavaScript有3大对象,分别是本地对象、内置对象和宿主对象。
在此引用ECMA-262(ECMAScript的制定标准)对于他们的定义:

  • 本地对象
    与宿主无关,独立于宿主环境的ECMAScript实现提供的对象。
    简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。
    这些引用类型在运行过程中需要通过new来创建所需的实例对象。
    包含:Object、Array、Date、RegExp、Function、Boolean、Number、String等。

  • 内置对象
    与宿主无关,独立于宿主环境的ECMAScript实现提供的对象。
    在 ECMAScript 程序开始执行前就存在,本身就是实例化内置对象,开发者无需再去实例化。
    内置对象是本地对象的子集。
    包含:Global和Math。
    ECMAScript5中增添了JSON这个存在于全局的内置对象。

  • 宿主对象
    由 ECMAScript 实现的宿主环境提供的对象,包含两大类,一个是宿主提供,一个是自定义类对象。
    所有非本地对象都属于宿主对象。
    对于嵌入到网页中的JS来说,其宿主对象就是浏览器提供的对象,浏览器对象有很多,如Window和Document等。
    所有的DOM和BOM对象都属于宿主对象。

复制对象

当复制一个对象是时,需要判断其实引用值还是原始值。
原始值可以直接复制数据,但是引用值需要复制引用的环境。
这就分成了浅度克隆和深度克隆

  • 浅克隆
    基本类型 值传递
    引用类型 地址传递
    深度克隆
    var obj = {
        name : 'abc',
        age : 12,
        card : ['visa','master'],
        car : {
            name : 'bwm',
            BuyYear : 2013,
            ID : 'Id9067'
        }
    }

//    1.判断是不是原始值    null
//    2.判断是数组还是对象。遍历数组,重新进行上个步骤。  toString ,instanceof ,constructor
//    3.建立相应的数组或对象

    function deepClone(origin,target){
        var target = target || {};
        for(var prop in origin)
        {
            if(origin.hasOwnProperty(prop)){
                if(typeof(origin[prop]) == 'object' && origin[target] !== null){
                    if(Object.prototype.toString.call(origin[prop]) == '[object Array]'){     
                    //哇,原来object是小写开头的,哭了。
                        target[prop] = [];
                    }else{
                        target[prop] = {};
                    }

                    // 以上的if,else可以用三目运算符代替。
                    // target[prop] = (Object.prototype.toString.call(origin[prop]) == '[object Array]')?[]:{};
                    deepClone(origin[prop],target[prop]);
                }
                else{
                    target[prop] = origin[prop];
                }
            }
        }
        return target;
    }
    var obj1 = {};
    deepClone(obj,obj1);

对象的属性

从 ES5 开始,所有的属性都具备了属性描述符。比如:

    var myObject = { 
        a:2
    };
    Object.getOwnPropertyDescriptor( myObject, "a" ); 
    // { 
    // value: 2,
    // writable: true,
    // enumerable: true,
    // configurable: true
    // } 

如你所见,这个普通的对象属性对应的属性描述符可不仅仅只是一个 2。它还包含另外三个特性:writable(可写)、 enumerable(可枚举)和 configurable(可配置)。 在创建普通属性时属性描述符会使用默认值,我们也可以使用 Object.defineProperty(…) 来添加一个新属性或者修改一个已有属性(如果它是 configurable)并对特性进行设置。

  • setter,getter
    操作属性值时的隐藏函数;
    setter在设置属性值时调用
    getter在获取属性值时调用
var myObject = { 
// 给 a 定义一个 getter 
     get a() {
     return this._a_; 
     },
// 给 a 定义一个 setter 
     set a(val) {
     this._a_ = val * 2; 
     } 
};
myObject.a = 2; 
myObject.a; // 4

对象值的遍历

在对象中我们可以使用for in语句遍历对象的可枚举属性,若要遍历属性的值,在es6中提出了for of函数。但是对象里面没有@@iteractor,不能手动遍历。

var myObject = {
a: 2,
b: 3
};
Object.defineProperty( myObject, Symbol.iterator, {
enumerable: false,
writable: false,
configurable: true,
value: function() {
var o = this;
var idx = 0;
var ks = Object.keys( o );
return {
next: function() {
return {
value: o[ks[idx++]],
done: (idx > ks.length)
};
}
};
}
} );
// 手动遍历 myObject
var it = myObject[Symbol.iterator]();
it.next(); // { value:2, done:false }
it.next(); // { value:3, done:false }
it.next(); // { value:undefined, done:true }
// 用 for..of 遍历 myObject
for (var v of myObject) {
console.log( v );
}
// 2
// 3

很巧妙的一道题。
不改变下面代码,输出o的中的所有属性值

    var foo = (function(){
        var o = {
           a: 1,
           b: 2,
           /**更多属性**/
        };
        return function(key) {
            return o[key];
        }
    })();

要获取o中的属性值,首先要将o提取出来。
结合上面的知识,在函数getter和setter中,this指向事件本身,因此只要在o取值的时候绑定get即可。现在给o增添一个属性,方便监听。由于对象的原型都是Object,只需在Object.prototype上编写。

Object.definePrototype(Object.prototype,"self",{
   get() {
     return this;
   }
});
var o = foo("self");   //调用get函数,取得o
console.log(Object.keys(o));// 利用Object上的keys函数将o中的属性遍历。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值