《你不知道的JavaScript》上卷-第三章 引用类型-对象知识点总结

78 阅读4分钟

先来看看数据类型中对象的定义。引用类型的值(对象)是引用类型的一个实例。注意,本文讨论的对象与类中的对象不同。

一、语法

对象通过两种形式来定义,声明(文字)类型和new构造形式。

(1)对象字面量表示法。声明对象的简写方式。           

    var obj={       key:value,       name:'liangzai'       //...    }

(2)new操作符后面跟object构造函数。

    var myobj=new Object();    myobj.key=value;

二、类型

js的内置类型;String、Number、Boolean、Object、Function、Array、Date、RegExp、Error。

在js中,实际上这些内置类型是只是一些内置函数。这些内置函数可以当作构造函数来使用,从而可以构造一个对应子类型的新对象。

看以下代码

   var str="I am string";   console.log(str.length);//11   console.log(str.charAt(0)) //I

由字面量定义的字符串上可以访问属性和方法,是因为js引擎自动会把字面量转成String对象,所以可以访问属性和方法。

需注意的是,new和undefined没有对应的构造形式,它们只有文字形式,相反,Date只有构造,没有文字形式。

三、内容

对象的内容是由一些存储在特定命名位置的值组成的,也就是属性。需注意一点,对象的内容一般不会存在对象容器内部,存储在对象容器内部的是这些属性的名称,它们就像指针一样,指向这些值真正的存储位置。

  var obj={       a:2    }   console.log(obj.a)   console.log(obj['a']);

如果要访问对象中的值,有两种方式,使用.操作符或者[]操作符。 .a语法通常被称为"属性访问"。['a']语法通常被称为"键访问"。

在对象中,属性名永远都是字符串。即使使用数字作为属性名,它首先会被转换为一个字符串。

3.1 可计算属性名

ES6中增加了可计算属性名。就是通过表达式来计算属性名。

    var prefix="foo";    var myobj={       [prefix+'bar']:'hello',    }   console.log(myobj['foobar']) //hello

3.2属性与方法

访问的对象属性是一个函数,有的人的叫法是方法,因为在类中通常被称为方法。

作者认为在对象中属性如果是函数,“方法”的叫法并不合适。因为对象中对于属性函数的访问,它只是返回一个函数,虽然某些函数有this引用,而this确实会指向调用位置的对象引用,但是本质上并没有把一个函数变成一个方法。

3.3复制对象

深拷贝和浅拷贝

深拷贝: 

方法:

var newObj=JSON.parse(JSON.stringfy(someObj));

原理是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象

浅拷贝: object.assign(...)第一个参数是目标对象,之后还可以跟多个源对象。

3.4 属性描述符

var obj={};Object.defineProperty(obj,"a",{ //定义属性value:2,writable:true, //决定是否可以修改属性的值configurable:true,//属性是否可以修改,禁止删掉a这个属性;enumerable:true //是否会出现在对象的属性枚举中 ,即是否会出现在对象的for in循环中})

3.5 不变性

如果想让属性或者对象是不可改变的,有多种方法可以实现。注意的是,所有的方法创建的都是浅不变性。也就是只会影响目标对象和它的直接属性,如果目标对象引用了其他对象(数组、函数等),其他对象的内容不受影响。

1、对象常量

结合writable:false和configurable:false可以创建一个真正的常量属性。(不可修改,重定义或者删除)

2、禁止拓展:

如果想禁止一个对象添加新属性并且保留已有属性。可以使用Object.preventExtensions(...)

 var obj={a:2}; Object.preventExtensions(obj); obj.b=3 console.log(obj.b) //undefined

在严格模式下,将会抛出typeError错误。

3、密封

Object.seal(..)会创建一个“密封”的对象,这个方法实际上会在一个现有对象调用Object.preventExtensions(...)并且把所有的属性标记为configurable:false。密封之后,不能添加新属性,也不能重新配置或者删除任何现有属性。

4、冻结

Object.freeze(...)会创建一个冻结对象,这个方法实际上在一个现有对象上调用Object.seal(...)并把所有“数据访问”属性标记为writable:false。

5、Getter和Setter

[[Get]]和[[Put]]可以控制属性值的设置和获取。

对象内置的[[Get]]操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。

6、存在性

  var obj={a:2};
 console.log('a'in obj) //true console.log(obj.hasOwnProperty('a'))//true

in操作符会检查属性是否存在对象及其[[Prototype]]原型链中。相比之下,Object.hasOwnProperty(...)只会检查属性是否在obj中,不会检查[[Prototype]]原型链。Object.propertyIsEnumberable(...)会检查给定的属性是否直接存在于对象中;

Object.keys(...)会返回一个数组,包含所有可枚举属性;Object.getOwnPropertyNames(...)会返回一个数组,包含所有属性,无论它们是否可枚举。