深刻探究JavaScript对象系列(二)

       上文中提到JavaScript对象是属性的集合,本结就来谈谈对象的属性以及对属性的操做。我的认为,JavaScript中对象的属性比其余语言复杂不少,因为本屌的主业是PHP,所以当初看书时候也花了不少时间才把这部份内容给理清了。javascript

 

 

一.JavaScript属性概述

       跟传统的面向对象不太同样,JavaScript对象是动态的,便可以随时对一个js对象新增或删除属性,对属性最多见的操做是设置、查找、删除、检测、枚举。除此之外,每一个属性还有一些与之相关的值,称为“属性特性”:java

  • 可写:代表该属性是否能够设置该属性的值;
  • 可枚举:代表是否能够经过for/in循环返回该属性;
  • 可配置:代表是否能够删除或建立该属性。

       正是因为上述3中属性特性使得JavaScript中属性相对其余语言来讲复杂了不少。此外,根据属性的定义位置,能够把属性分为:数组

  • 自有属性:直接在对象中定义的属性;
  • 继承属性:在对象的原型对象中定义的属性。

 

 

二.对属性的设置和查询

      因为对象的属性一部分是由本身定义,还有一部分属性是从原型对象那继承下来,所以假如要查询对象o中的属性x时,若是o中不存在,js引擎将会陆续在o的原型对象中来寻找x,若是整条原型链中都找不到或者找到一个原型是null的对象,则返回undefined函数

var o = {};
o.x = 1;
p = inherit(o);  //建立一个新对象p,原型对象为o,inherit函数请查看上一篇
console.log(p.x);  //返回1,因为在对象p中找不到属性x,则js引擎在它的原型对象中继续查找

       如今假设给给对象o的属性x赋值,若是o中以及有自有属性x,则赋值操做值就直接改变该属性的值,若是不存在,则赋值操做给o新增这个属性x。若是o中的原型链中也有该属性,则继承的属性就被这个新建立的属性覆盖了。this

       上述对属性的赋值是基于一种理想状况,事情每每不会那么简单,上面以及提到,每个属性都有3个属性特性:可写、可枚举、可设置,若是对象o中继承了一个只读属性的x,则赋值操做是不被容许的。spa

        在JavaScript中,只有在查询属性时,才能体会到继承的存在。code

 

 

三.删除对象的属性

       删除一个JavaScript对象的属性可使用delete运算符,然而须要注意的是:delete只是断开属性和宿主对象的联系,而不会去操做属性中的属性,在销毁一个对象时应特别注意这点;此外delete只能删除自有属性,不能删除继承属性,所以若是要删除继承属性,须要先找到原型链中的该拥有该属性的对象才能删除它。对象

       若是碰到那种可配置性为false的属性,如经过变量声明或函数声明建立的全局的对象,是不能被删除的,在严格模式下,删除一个不可配置的属性会报一个类型错误。blog

 

 

四.属性的检测和枚举

       检测一个属性是否属于某个对象有如下几种方法:继承

  • in运算符:若是对象的自有属性或继承属性中有这个属性则返回true;
  • hasOwnProperty():对象的这个方法用来检测给定的名字是否是对象的自有属性,对于继承的属性返回false;
  • propertyIsEnumerable():该方法是hasOwnProperty()方法的加强版,只有检测到是自有属性且该属性是可枚举的才返回true;
    var o ={};
    o.x = 1;
    p = inherit(o);
    p.y = 2;
    
    o.hasOwnProperty("x");   //返回true
    p.hasOwnProperty("x");   //返回false
    
    Object.property.propertyIsEnumerable("toString");   //返回false,toString()方法不可枚举
    

     

       经过for/in循环能够遍历出对象中全部可枚举的属性(包括自有属性和继承属性),通常来讲,对象的内置方法是不可枚举的,但在代码中定义的属性一般都是能够枚举,除非显式地指定该属性为不可枚举,例如:

var o ={x:1 , y:2, z:3};

o.propertyIsEnumerable("toString");  //返回false

for(p in o){
  console.log(p);
}          //循环输出1,2,3,但不会输出toString.

       在ECMAScript5中定义了两个用于枚举属性名称的函数Object.keys()和Object.getOwnPropertyNames(),前者返回一个由对象中可枚举且自有属性组成的数组,后者也返回一个数组,可是它返回的是自有属性的名称,无论其是否可枚举,在ECMAScript3中能够用如下方法来模拟前者:

1 function keys(o){
2     if(typeof o !== "object") throw TypeError();
3     var result = [];
4     for(prop in o){
5         if (!o.hasOwnProperty(prop)) continue;
6         else result.push(prop);
7     }
8     return result;
9 }

 

 

五.属性getter和setter

       在ECMAScript5中,属性值能够用一个或两个方法替代,这两个方法就是getter和setter,由这两个方法定义的属性称做“存取器属性”,不一样于“数据”属性,它不具备写属性。

       若是一个存取器属性同时具备getter和setter方法,则这个属性是可读写的,若是只有getter那么它就是个只读属性;若是只有setter方法,则是一个只写属性,读取它时返回undefined

var o ={
    x : 2,
    y : 3,

    get z(){
        return this.x*this.y;
    },
    set z(value){
        this.x += value;
        this.y += value;
    }
};

console.log(o.z);   //返回6

o.z = 2;

console.log(o.z);      //返回20
相关文章
相关标签/搜索