眼前的说话
对于对象来说,属性操作是纠缠不起之话题。类似于“增删改查”的基本操作,属性操作分为属性查询、属性设置、属性删除,还连属性持续。本文是目标系列的次篇——属性操作
性能查询
属性查询一般生有限种方法,包括点运算符和方括号运算符
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;
[注意]关于逻辑与&&运算符的使移动至此
null和undefined未是目标,给其设置属性会报错
null.a = 1;//Uncaught TypeError: Cannot set property 'a' of null
undefined.a = 1;//Uncaught TypeError: Cannot set property 'a' of undefined
由于string、number和boolean来相应之卷入对象,所以叫她设置属性不见面报错
'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章 对象的恢宏