JS简记-对象

js中有六大类型:string、number、boolean、object、null、undefined。

console.log(typeof "123");//string
console.log(typeof 123);//number
console.log(typeof true);//boolean
console.log(typeof {});//object
console.log(typeof null);//object
console.log(typeof undefined);//undefined

其中string、number、boolean、null、undefined称为简单基本类型,object为对象类型。js有两种生成对象的方式,一种是字面量(var o = {...}),另一种是构造调用(var o = new Array(...)),通常我们都会使用第一种字面量形式。访问对象属性也有两种方式,一种是通过“.”访问,另一种是通过“[]”访问,通常使用前者访问,但通过后者可以定义/访问动态属性名,功能更加强大(比如obj[a+b]=1)。

最基础的类型为对象类型的对象为Object,Object有很多子对象,比如String、Number、Boolean,Function、Array等,String、Number、Boolean可以看成是基本类型string、number、boolean的包装类型,js引擎在执行时如果有必要会自动将基本类型“打包”成其相应的对象类型。

 通常情况下,所有的对象类型都会“继承”Object对象,但也有例外的情况:

var a1 = {};
var a2 = Object.create(null);

查看window的这两个属性,a2便不“继承”Object对象:

 

String

常用方法:concat,indexOf,lastIndexOf,replace,split,substr,substring等。

Number

常用方法:toFix,toString等。

Boolean

Array

常用方法:concat,join,push,pop,shift,sort

数组在使用“[]”操作属性时,如果"[]"中的内容为字符串型的数字则会被视为数字,从而对数组元素进行操作。而普通对象在使用“[]”操作属性时,则会将“[]”中的数字视为字符串,从而对对象属性进行操作。

var arr = ["a"];
arr.push("b");
console.log(arr[1]);//b
console.log(arr["1"]);//
console.log(arr.length);//2

var obj = {0: "a"};
obj[1] = "b";
console.log(obj[1]);//b
console.log(obj["1"]);//b

 

Function

Date

RegExp

Error

 

复制对象内容

var newObj = JSON.parse(JSON.stringify(obj));

ES6提供的浅复制方法Object.assign(target, ......sources)

var newObj = Object.assign(Object.create(null), obj1, obj2);

 数据描述符访问描述符

 

从ES5开始,我们可以通过Object.getOwnPropertyDescriptor获取对象的属性描述符(描述对象属性的一个数据结构(对象),又分为数据描述符和访问描述符)

var obj = {
    a: "hello"
}
console.log(Object.getOwnPropertyDescriptor(obj, "a"));

控制台打印如下,可以看到一个对象的某个属性的数据描述符是一个Object的子对象,且一个数据描述符对象拥有value、writable、enumerable、configurable四个属性。

同样的,我们可以对属性描述符进行设置:

var obj = {};
Object.defineProperty(obj, "a", {
    value: 2,
    writable: true,
    configurable: true,
    enumerable: true
});
obj.a;// 2

我们在访问对象的属性时,看似是直接操作于该属性,实则js引擎会通过调用内部的[[Get]]/[[Put]]逻辑对属性进行操作,这时属性描述符对象就有用了。比如obj.a=3,这时就会走[[Put]]逻辑,首先判断a属性是否存在,如果存在,[[Put]]会判断a属性是否可写,即writable是否为true,如果为true才会更新a的值。

通过数据描述符,我们就可以对对象属性进行访问控制了,比如是否可更新,是否可枚举(通过for in遍历)。ES5进一步提供了一些方法用于控制对象属性的访问策略,比如可以通过Object.preventExtensions(..)、Object.seal(..)、Object.freeze(..)等函数设置对象(及其属性)的不可变性级别。

[[Get]]/[[Put]]是js引擎内部逻辑,我们是否可以重写某些属性的[[Get]]/[[Put]]逻辑呢?ES5中,可以使用getter/setter重写默认逻辑(也可以这样理解,[[GET]]/[[PUT]]首先会尝试getter/setter,如果二者未定义则使用数据描述符,访问描述符和数据描述二者只能定义其一),getter/setter就被称为访问描述符

 1 obj = {
 2     a: "hello",
 3     get a(){//必须放在a: "hello"之后,否则会被默认逻辑覆盖
 4         return "world";
 5     },//默认enumerable:true, configurable:true
 6 }
 7 console.log(obj.a);//world
 8 //or
 9 Object.create(null, {
10     {
11         a: {
12             get: function(){return "world";},
13             set: function(value){this._a_ = value},
14             enumerable: true,
15             configurable: true,//不能对访问描述符设置writable和value
16         }
17     }
18 });    

 

对象的遍历

我们知道数组可以使用for in,通过数组元素的索引来遍历数组。ES6中数组对象内部提供了一个迭代器(可以通过属性名Symbol.iterator查看,是一个native code),可以通过该迭代器实现for of遍历:

var arr = ["a", "b", "c"];
for(let v of arr){
    console.log(v);//通过for of得到的是数组的值,而不需要再通过索引来找值了
}

除了for of,ES5数组还有forEach、every、some等遍历函数。

js对象很像一个map,key就是属性名,value就是属性值,那么普通对象是否可以像数组一样使用for of进行遍历呢?js并没有为普通对象提供类似的迭代器,我们只能使用for in通过数组元素的索引对数组进行遍历。但我们可以自定义一个迭代器,通过该迭代器就可以使用for of了:

 1 function generateIterator(){
 2     var obj_ = this;
 3     var keys = Object.keys(obj);
 4     var i = 0;
 5     return {
 6         next: function(){
 7             return {
 8                 value: obj_[keys[i++]],
 9                 done: i>keys.length
10             }
11         }
12     }
13 }
14 var obj = {
15     a: "hello",
16     b: "world"
17 };
18 Object.defineProperty(obj, Symbol.iterator
19     , {
20         writable: false,
21         enumerable: false,
22         configurable: true,
23         value: generateIterator
24     });
25 //手动遍历
26 for(let ite=obj[Symbol.iterator](), next=ite.next(); !next.done; next=ite.next()){
27     console.log(next.value);
28 }
29 //for of
30 for(var v of obj){
31     console.log(v);
32 }

 

posted @ 2018-05-01 18:03  holoyong  阅读(145)  评论(0编辑  收藏  举报