深深了然javascript对象体系第二篇——属性操作

前方的话

  对于对象来说,属性操作是绕不开的话题。类似于“增删改查”的基本操作,属性操作分为属性查询、属性设置、属性删除,还包括属性持续。本文是目标体系的第二篇——属性操作

 

属性查询

  属性查询一般有两种情势,包括点运算符和方括号运算符

var o = {
  p: 'Hello World'
};
o.p // "Hello World"
o['p'] // "Hello World"

  [注意]变量中可以存在闽南语,因为粤语相当于字符,与英文字符同样对待,由此得以写成person.白或person[‘白’]

var person = {
    白 : 1
}
person.白;//1
person['白'];//1

【点运算符】

  点运算符是多多益善面向对象语句的通用写法,由于其相比较简单,所以较方括号运算符相比,更常用

  由于javascript是弱类型语言,在其他对象中都可以创设任意数量的习性。但当通过点运算符(.)拜访对象的特性时,属性名用一个标识符来代表,标识符要符合变量命名规则。标识符必须从来出现在javascript程序中,它们不是数据类型,因而先后不能修改它们

var o = {
    a:1,
    1:2
};
console.log(o.a);//1
//由于变量不可以以数字开头,所以o.1报错
console.log(o.1);//Uncaught SyntaxError: missing ) after argument list

【方括号运算符】

  当通过方括号运算符([])来走访对象的属性时,属性名通过字符串来表示。字符串是javascript的数据类型,在程序运行中得以修改和创制它们

  使用方括号运算符有五个亮点

  【1】可以透过变量来做客属性

var a = 1;
var o = {
    1: 10
}
o[a];//10

  【2】属性名称可以为javascript无效标识符

var myObject = {
    123:'zero',
    class:'foo'
};
console.log(myObject['123'],myObject['class']);//'zero' 'foo'
console.log(myObject.123);//报错

  方括号中的值倘若非字符串类型会动用String()隐式转换成字符串再出口;假诺是字符串类型,若有引号则原值输出,否则会被辨认为变量,若变量未定义,则报错

var person = {};
person[0];  //[]中的数字不会报错,而是自动转换成字符串
person[a];  //[]中符合变量命名规则的元素会被当成变量,变量未被定义,而报错
person['']; //[]中的空字符串不会报错,是实际存在的且可以调用,但不会在控制台右侧的集合中显示

person[undefined];//不会报错,而是自动转换成字符串
person[null];//不会报错,而是自动转换成字符串
person[true];//不会报错,而是自动转换成字符串
person[false];//不会报错,而是自动转换成字符串

可总结属性名

  在方括号运算符内部可以利用表明式

var a = 1;
var person = {
    3: 'abc'
};
person[a + 2];//'abc'

  但要是要在目的字面量内部对属性名使用说明式,则需要采纳ES6的可总计属性名

var a = 1;
//Uncaught SyntaxError: Unexpected token +
var person = {
    a + 3: 'abc'
};

  ES6充实了可统计属性名,可以在文字中应用[]卷入一个表明式来当作属性名

var a = 1;
var person = {
    [a + 3]: 'abc'
};
person[4];//'abc'

性能查询错误

  【1】查询一个不存在的特性不会报错,而是重返undefined

var person = {};
console.log(person.a);//undefined

  【2】假诺目的不设有,试图询问这几个不设有的目的的习性会报错

console.log(person.a);//Uncaught ReferenceError: person is not defined

  可以采取这点,来检查一个全局变量是否被声称

// 检查a变量是否被声明
if (a) {...} // 报错

//所有全局变量都是window对象的属性。window.a的含义就是读取window对象的a属性,如果该属性不存在,就返回undefined,并不会报错
if (window.a) {...} // 不报错

 

性能设置

  属性设置又叫做属性赋值,与特性查询同一,具有点运算符和方括号运算符这二种办法

o.p = 'abc';
o['p'] = 'abc';

  在给目的设置属性在此以前,一般要先检测对象是不是存在

var len = undefined;
if(book){
    if(book.subtitle){
        len = book.subtitle.length;
    }
}

  下边代码可以简化为

var len = book && book.subtitle && book.subtitle.length;

  [注意]关于逻辑与&&运算符的选取移动至此

  nullundefined不是目的,给它们设置属性会报错

null.a = 1;//Uncaught TypeError: Cannot set property 'a' of null
undefined.a = 1;//Uncaught TypeError: Cannot set property 'a' of undefined

  由于stringnumberboolean有相应的卷入对象,所以给它们设置属性不会报错

'abc'.a = 1;//1
(1).a = 1;//1
true.a = 1;//1

 

特性删除

  使用delete运算符可以去除对象属性(包括数组元素)

var o = {
    a : 1
};
console.log(o.a);//1
console.log('a' in o);//true
console.log(delete o.a);//true
console.log(o.a);//undefined
console.log('a' in o);//false

  [注意]给目的属性置null或undefined,并不曾去除该属性

var o = {
    a : 1
};
o.a = undefined;
console.log(o.a);//undefined
console.log('a' in o);//true
console.log(delete o.a);//true
console.log(o.a);//undefined
console.log('a' in o);//false

  使用delete删除数组元素时,不会改变数高管度

var a = [1,2,3];
delete a[2];
2 in a;//false
a.length;//3

  delete运算符只好删除自有总体性,无法去除继承属性(要删减继承属性必须从概念这多少个特性的原型对象上剔除它,而且这会影响到持有继续自那多少个原型的靶子)

var o  = {
    a:1
}
var obj = Object.create(o);
obj.a = 2;

console.log(obj.a);//2
console.log(delete obj.a);//true
console.log(obj.a);//1
console.log(delete obj.a);//true
console.log(obj.a);//1

返回值

  delete操作符的重回值是个布尔值true或false

  【1】当使用delete操作符删除对象属性或数组元素删除成功时,再次回到true

var o = {a:1};
var arr = [1];
console.log(delete o.a);//true
console.log(delete arr[0]);//true

  【2】当使用delete操作符删除不存在的习性或非左值时,返回true

var o = {};
console.log(delete o.a);//true
console.log(delete 1);//true
console.log(delete {});//true

  【3】当使用delete操作符删除变量时,重临false,严苛模式下会抛出ReferenceError错误

var a = 1;
console.log(delete a);//false
console.log(a);//1

'use strict';
var a = 1;
//Uncaught SyntaxError: Delete of an unqualified identifier in strict mode
console.log(delete a);

  【4】当使用delete操作符删除不可配置的特性时,重临false,严峻格局下会抛出TypeError错误

var obj = {};
Object.defineProperty(obj,'a',{configurable:false});
console.log(delete obj.a);//false

'use strict';
var obj = {};
Object.defineProperty(obj,'a',{configurable:false});
//Uncaught TypeError: Cannot delete property 'a' of #<Object>
console.log(delete obj.a);

 

性能持续

  每一个javascript对象都和另一个对象相关联。“另一个目的”就是我们熟习的原型,每一个对象都从原型继承属性。所有通过对象直接量创设的对象都持有同一个原型对象,并可以透过Object.prototype得到对原型对象的引用

var obj = {};
console.log(obj.__proto__ === Object.prototype);//true

  [注意]Object.prototype的原型对象是null,所以它不连续任何性质

console.log(Object.prototype.__proto__ === null);//true

  对象自我有着的属性叫自有性能(own
property),从原型对象继承而来的性能叫接轨属性

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
//继承自原型对象o的属性a
console.log(obj.a);//1
//自有属性b
console.log(obj.b);//2

in

  in操作符可以断定属性在不在该对象上,但无法区分自有依旧连续属性

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
console.log('a' in obj);//true
console.log('b' in obj);//true
console.log('b' in o);//false

for-in

  通过for-in循环可以遍历出该对象中保有可枚举属性 

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
for(var i in obj){
    console.log(obj[i]);//2 1
}

hasOwnProperty()

  通过hasOwnProperty()方法可以确定该属性是自有性能如故延续属性

var o = {a:1};
var obj = Object.create(o);
obj.b = 2;
console.log(obj.hasOwnProperty('a'));//false
console.log(obj.hasOwnProperty('b'));//true

Object.keys()

  Object.keys()方法再次回到所有可枚举的自有性能

var o = {a:1};
var obj = Object.create(o,{
    c:{value:3,configurable: false}
});
obj.b = 2;
console.log(Object.keys(obj));//['b']

Object.getOwnPropertyNames()

  与Object.keys()方法不同,Object.getOwnPropertyNames()方法重回所有自有总体性(包括不可枚举的属性)

var o = {a:1};
var obj = Object.create(o,{
    c:{value:3,configurable: false}
});
obj.b = 2;
console.log(Object.getOwnPropertyNames(obj));//['c','b']

 

参考资料

【1】 W3School-Javascript高级教程——对象应用
http://www.w3school.com.cn/js/
【2】 阮一峰Javascript标准参照教程——对象
http://javascript.ruanyifeng.com/grammar/object.html
【3】《javascript权威指南(第6版)》第6章 对象
【4】《javascript高级程序设计(第3版)》第6章 面向对象的主次设计
【5】《javascript语句雅观》第3章 对象
【6】《javascript面向对象精要》 第3章 理解对象
【7】《你不理解的javascript上卷》第3章 对象
【8】《ECMAScript6入门》 第7章 对象的扩充