1

对象的定义语法

声明形式

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)并对特性进行设置。

不变性

  1. 对象常量:结合writable:false和configurable:false就可以创建一个真正的常量属性。
  2. 禁止拓展:Object.preventExtensions(...)
  3. 密封:Object.seal(...)会创建一个密封的对象,实际上是在一个现有对象上调用Object.preventExtensions(...)并把所有现有属性标记为configurable:false。所以密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以修改属性的值)。
  4. 冻结: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);//false

myObj.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

Teemo
38 声望1 粉丝