1.概述
对象Object是js的核心概念,最重要的数据类型,对象就是一种无序的数据集合,由若干键值对(key-value)构成
示例:
var o={
p:'hello world'
};
对象的3个生成方法
示例:
var o1={};
var o2=new Object();
var o3=Object.create(Object.prototype);
2.键名
对象的所有键名都是字符串,所以加不加引号都可以
示例:
var o={
'p':'hello world'
};
3.属性
对象的每个键名也称为属性,键值可以是任何数据类型,如果一个属性的值是函数,这个属性也被称为方法,它可以像函数那样调用
示例:
var o={
p:function(x){
return 2*x;
}
};
o.p(1);//2
属性可以动态创建,不必再对象声明时就指定
示例:
var obj={};
obj.foo=123;
obj.foo;//123
4.对象的引用
如果不同的变量名指向同一个对象,那么他们都是这个对象的引用,就是指向同一个内存地址,修改其中一个变量,会影响到其他变量
示例:
var o1={};
var o2=o1;
o1.a=1;
o2.a//1
o2.b=2;
o1.b//2
5.表达式还是语句
如果行首是大括号,一律解释为语句,如果要解释为表达式,必须再大括号前加上圆括号
示例:
({foo:123})
如果没有圆括号,eval将其理解为一个代码块;加上圆括号以后,就理解成一个对象
示例:
eval('{foo: 123}') // 123
eval('({foo: 123})') // {foo: 123}
6.属性的操作
读取对象的属性,一种是使用点运算符,另一种是使用方括号运算符
示例:
var o={
p:'hello world'
};
o.p//"hello world"
o['p']//"hello world"
7.检查变量是否声明
如果读取一个不存在的键,会返回undefined,而不是报错,可以利用这点检查一个全局变量是否被声明
示例:
if(a){...}//报错
if(window.a){...}//不报错
if(window['a']){...}//不报错
上面的后二种写法之所以不报错,是因为在浏览器环境,所有全局变量都是window对象的属性。window.a的含义就是读取window对象的a属性,如果该属性不存在,就返回undefined,并不会报错。
需要注意的是,后二种写法有漏洞,如果a属性是一个空字符串(或其他对应的布尔值为false的情况),则无法起到检查变量是否声明的作用。正确的做法是可以采用下面的写法
if('a' in window){
//变量a声明过
}else{
//变量a未声明
}
8.属性的赋值
点运算符和方括号运算符不仅可以用来读取值,还可以用来赋值
示例:
o.p='abc';
o['p']='abc';
查看所有属性可以使用Object.keys方法
示例:
var o={
key1:1,
key2:2
};
Object.keys(o);//['key1','key2']
delete命令用于删除对象的属性,删除成功后返回true
示例:
var o={p:1};
Object.keys(o)//["p"]
delete o.p;//true
o.p//undefined
Object.keys(o)//[]
delete命令会返回false,那就是该属性存在,且不得删除
示例:
var o=Object.defineProperty({},'p',{
value:123,
configurable:false
});
o.p;//123
delete o.p;//false
delete命令只能删除对象本身的属性,无法删除继承的属性
示例:
var o = {};
delete o.toString // true
o.toString // function toString() { [native code] }
toString是对象o继承的属性,虽然delete命令返回true,但该属性并没有被删除,依然存在
delete命令不能删除var命令声明的变量,只能用来删除属性
示例:
var p = 1;
delete p // false
delete window.p // false
9.in运算符
in运算符用来检查对象是否包含某个属性,检查的是键名不是键值,如果包含返回true,否在返回false
示例:
var o={
p:1
};
'p' in o;//true
在js中,所有全局变量都是顶层对象(浏览器的顶层对象就是window对象)的属性,因此可以用in运算符判断,一个全局变量是否存在
示例:
// 假设变量x未定义
// 写法一:报错
if (x) { return 1; }
// 写法二:不正确
if (window.x) { return 1; }
// 写法三:正确
if ('x' in window) { return 1; }
上面三种写法之中,如果x不存在,第一种写法会报错;如果x的值对应布尔值false(比如x等于空字符串),第二种写法无法得到正确结果;只有第三种写法,才能正确判断变量x是否存在
in运算符的一个问题是,它不能识别对象继承的属性
示例:
var o=new Object();
o.hasOwnProperty('toString');//false
'toString' in o;//true
上面代码中,toString方法不是对象o自身的属性,而是继承的属性,hasOwnProperty方法可以说明这一点。但是,in运算符不能识别,对继承的属性也返回true
10.for...in循环
for...in循环用来遍历一个对象的全部属性
示例:
var o={a:1,b:2,c:3};
for(var i in o){
console.log([i]);
}
//1
//2
//3
for...in循环有两个使用注意点
第一,它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性
第二,它不仅遍历对象自身的属性,还遍历继承的属性
示例:
// name 是 Person 本身的属性
function Person(name) {
this.name = name;
}
// describe是Person.prototype的属性
Person.prototype.describe = function () {
return 'Name: '+this.name;
};
var person = new Person('Jane');
// for...in循环会遍历实例自身的属性(name),
// 以及继承的属性(describe)
for (var key in person) {
console.log(key);
}
// name
// describe
如果只想遍历对象本身的属性,可以使用hasOwnProperty方法,在循环内部判断一下是不是自身的属性
示例:
for (var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
// name
一般情况下,都是只想遍历对象自身的属性,所以不推荐使用for...in循环
11.with语句
with用来操作同一个对象的多个属性时,提供一些书写的方便
示例:
// 例一
with (o) {
p1 = 1;
p2 = 2;
}
// 等同于
o.p1 = 1;
o.p2 = 2;
// 例二
with (document.links[0]){
console.log(href);
console.log(title);
console.log(style);
}
// 等同于
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);
注意,with区块内部的变量,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量。这是因为with区块没有改变作用域,它的内部依然是当前作用域
它的使用场合很少