对象的定义语法
声明形式
var myObj={key:value,...
}
构造形式
var myObj=new Object();
myObj.key=value;
JS的六种主要类型
- string
- number
- boolean
- null
- undefined
- object
内置对象(对象子类型)
- String
- Number
- Boolean
- Object
- Function
- Array
- Date
- RegExp
- Error
内容
var myObj={a:2
};myObj.a;//2——属性访问myObj["a"];//2——键访问
可计算属性名
可以在文字形式中使用[ ]包裹一个表达式来当作属性名。
属性与方法
从技术角度来说,函数永远不会“属于”一个对象,所以把对象内部引用的函数称为“方法”是不妥的。
数组
数组期待的是数值下标。最好只用对象来存储键/值对,只用数组来存储数值下标/值对。
如果试图向数组添加一个属性,但是属性名“看起来”像一个数组,那么它会变成一个数值下标(因此会修改数组的内容而不是添加一个属性)。
复制对象——浅复制
var newObj=Object.assign( {},myObject );
Object.assign方法的第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象的所有可枚举的自有键,并把它们复制(使用=操作符赋值)到目标对象,最后返回目标对象。
属性描述符
var myObj={a:2};Object.getOwnPropertyDescriptor(myObj,"a");
/*{value:2,writable:true,enumerable:true,configurable:true
}*/
普通的对象属性对应的属性描述符除了key:value,还包含另外三个特性:writable(可写)、enumerable(可枚举)、configurable(可配置,将其修改为false是单向操作,无法撤消)。
可以使用Object.defineProperty(...)
来添加一个新属性或者修改一个已有属性(如果它是configurable)并对特性进行设置。
不变性
- 对象常量:结合writable:false和configurable:false就可以创建一个真正的常量属性。
- 禁止拓展:
Object.preventExtensions(...)
。 - 密封:
Object.seal(...)
会创建一个密封的对象,实际上是在一个现有对象上调用Object.preventExtensions(...)
并把所有现有属性标记为configurable:false。所以密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以修改属性的值)。 - 冻结:
Object.freeze(...)
会创建一个冻结对象,实际上是在现有对象调用Object.seal(...)
并设置为writable:false,这样就无法修改它们的值。这是应用在对象上的级别最高的不可变性。
[[GET]]
对象默认的内置[[GET]]操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。如果无论如何都没有找到名称相同的属性,那[[GET]]操作会返回值undefined。需要注意的是,这种方法和访问变量时是不一样的。如果你引用了一个当前词法作用域中不存在的变量,并不会像对象属性一样返回undefined,而是会派出一个ReferenceError异常。
[[PUT]]
Getter和Setter
通常来说getter和setter是成对出现的。
存在性
var myObj={a:2
};("a" in myObj);//true
("b" in myObj);//falsemyObj.hasOwnProperty("a");//true
myObj.hasOwnProperty("b");//false
in操作符会检查属性是否在对象及其[[Prototype]]原型链中。hasOwnProperty(...)只会检查属性是否在myObj中,不会检查[[Prototype]]。
*:in实际上检查的是某个属性名是否存在。对于数组来说这个区别非常重要,4 in [2,4,6]的结果并不是你的期待的true,因为[2,4,6]这个数组中包含的属性名是0、1、2,没有4。
- 枚举
propertyIsEnumerable(...)//会检查给定的属性名是否直接存在于对象中
Object.keys(...)//会返回一个数组,包含所有可枚举属性
Object.getOwnpropertyNames(...)//会返回一个数组,包含所有属性,无论是否可枚举
遍历
forEach(...)//会遍历数组中的所有值并忽略回调函数的返回值
every(...)//会一直运行直到回调函数返回false
some(...)//会一直运行直到回调函数返回true
for...of
var myArray=[1,2,3];for(var v of myArray){console.log(v);
}
//1
//2
//3
自定义迭代器
var myObj={a:2,b:3
};Object.defineProperty(myObj,Symbol.iterator,{enumerable:false,writable:flse,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)};}};}
});//手动遍历myObj
var it=myObj[Sysbol.iterator]();
it.next();//{value :2,done:false}
it.next();//{value :3,done:false}
it.next();//{value :undefined,done:true}//用for...of遍历myObj
for (var v of myObj){console.log(v);
;//2
//3