对象和Object构造函数
没有单独区分出es6新增的一些属性方法
1.对象
创建一个对象
1 | var obj = {}; |
还可以通过new关键字创建一个对象实例
对象的属性
1) 如何设置以及访问对象的属性
1 | var obj = {}; |
这里有两个问题:
第一个问题:console.log(obj['[object Object]'])
,为什么设置属性的时候,键名是objKey这个对象,最后打印的时候键名要使用[object Object]
字符串
因为:在objKey被添加到obj的时候调用了objKey.toString()
方法,将返回的字符串作为了新键。
第二个问题:objKey对象上并没有toString
方法,所以就要爬原型链了,从__proto__
上找,其实也就是Object.prototype.toString
方法。通常我们用这个方法来区分对象和数组。
2)怎样的属性只支持使用方括号访问对象属性
1 | var obj = { |
当对象的属性是空格,分隔符,或者数字开头的时候,只能通过方括号取得它的值,因为它们不是有效的JavaScript标识符
3)枚举对象中所有属性
for…in…
1 | var obj = {a:1,b:2,c:3}; |
Object.keys(obj)
返回一个数组
1 | var obj = {a:1,b:2,c:3}; |
Object.getOwnPropertyNames(obj)
英文直译:获取私有的属性名字们,哈哈哈哈,返回一个数组
1 | var obj = {a:1,b:2,c:3}; |
4)getter与setter
getter:获取某个特定属性的值的方法
setter:设定某个特定属性的值的方法
1 | var obj = { |
2.Object构造函数
构造函数的方法
1)Object.assign(target, …sources)
对象合并,并且创建一个新的对象
target:目标对象
sources:原对象
1 | var obj1 = { a: 2, c: 3 }; |
2)Object.create(proto, [propertiesObject])
创建一个新的对象
proto:新创建对象的原型对象
propertiesObject:为新创建的对象添加可枚举的属性,如果不是null
或者对象
,则抛出异常
1 | var obj = {a:1,b:2}; |
打印出的obj1如图:
可以看到这个新对象,而它的__proto__
指向obj
,也就是说obj1.__proto__.__proto__ === Object.prototype
也就是说这个方法可以设置新建对象的__proto__
指向,如果第一个参数是null
的话
1 | var obj = Object.create(null); |
输出如图:
实现一个简单create方法
1 | Object.create = function (o) { |
3)Object.defineProperty(obj, prop, descriptor)
在一个对象上定义新的属性,或者修改已有的属性
obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptor:将被定义的属性描述符
属性描述符
:
configurable(默认值false):是否能删除对象上的属性。
enumerable(默认值false):是否能够枚举,比如for…in…
writable(默认值false):是否能修改属性值
value(默认值undefined):属性的值
get(默认值undefined):访问该属性的时候会执行对应的方法,没有参数传入
set(默认值undefined):访问该属性的时候会执行对应的方法,有参数传入
需要注意的就是:
1.如果第一次没设置属性描述符,则会使用默认值,修改(设置为相同的值则不算修改)
属性值的时候(除了value和writable)会扔出TypeError
,报错信息大概是这样:
2.设置了set或get,同时设置了value或者writable就报错了,报错信息如图:
这里是🌰,看一看属性描述符的特点:
1 | var obj = {}; |
这里configurable,enumerable,writable默认值false
。我们重新写一个设置这些属性为true
1 | var obj = {}; |
那么来实现一个简单的双向绑定吧!!!
1 |
|
如图:
通过JS修改obj.name
的值的时候,input
的value
与p
的innerHTML
都会改变。
4)Object.defineProperties(obj, props)
为对象设置多个属性
obj:要在其上定义属性的对象。
props:定义其可枚举属性或修改的属性描述符的对象
1 | var obj = {}; |
Object.defineProperty
与Object.defineProperties
的区别:
它们接受的参数不同,Object.defineProperty
为单个键名设置属性描述符
,而Object.defineProperties
第二个参数接受个对象是可以一次性设置多个键名与对应的属性操作符
5)Object.freeze(obj)
冻结对一个对象,也就是说对冻结的对象的任何属性都不能修改,这个方法返回被冻结的对象,而不是创建一个被冻结的副本
1 | var obj = {a:1}; |
6)Object.getOwnPropertyDescriptor(obj, prop)
返回指定对象上的键名对应的属性描述符
obj:指定的对象
prop:指定的键名
1 | var obj = {}; |
7)Object.getOwnPropertyDescriptors(obj)
上面那个方法需要指定键名,这个方法只需要指定对象
obj:指定的对象
1 | var obj = {}; |
打印结果如图:
8)Object.getOwnPropertyNames(obj)
返回对象的键名的数组(包括不可枚举的键名)
obj:指定的对象
1 | var obj = {}; |
9)Object.getPrototypeOf(obj)
返回obj的[[Prototype]]属性值
obj:指定的对象
1 | var obj = new Object({}); |
10)Object.setPrototypeOf(obj,prototype)
设置一个指定的对象的原型 就是设置对象 [[Prototype]] 属性指向到另一个对象
或 null
obj:指定的对象
prototype:该对象的新原型(一个对象或者null)否则报错TypeError
1 | var obj = { name: 'qinhanwen' }; |
打印的obj如图:
可以看到obj.__proto__ === obj1
,obj.__proto__.__proto__ === Object.prototype
,
11)Object.is(value1, value2)
判断两个值是否相同
value1:第一个值
value2:第二个值
1 | console.log(Object.is("", false));//false |
我们都知道==
如果两边的值的类型不同的话,则会把两边的值先进行隐式转换,之后再进行比较。
而它又与===
不同。
12)Object.keys(obj)
获得可枚举的对象的键名,返回个数组。
obj:指定的对象
1 | var obj = {name:'qinhanwen',age:25}; |
13)Object.values(obj)
返回可被枚举的键值
obj:指定的对象
1 | var obj = {}; |
Object构造函数的prototype上的方法
1)object.prototype.hasOwnProperty()
返回布尔值,判断对象上是否有某个键名
语法:obj.hasOwnProperty(prop)
prop:键名
1 | var obj = {}; |
说到这个方法,不得不说一下in
操作符
1 | var fn = function(){ |
可以看出hasOwnProperty
方法是判断实例上是否有某个属性,而in
操作符会判断实例,没有的话会往[[Prototype]]上找。
2)Object.prototype.isPrototypeOf()
返回布尔值,判断一个对象是否在另一个对象的原型链上
语法:prototypeObj.isPrototypeOf(obj)
obj:目标对象
prototypeObj:原型对象
1 | var obj = {}; |
说到这个方法,让我想到了instanceOf
,判断某个值是否在另外一个值的原型链上,实现一个instanceOf
方法
3)Object.prototype.toString()
返回一个表示该对象的字符串
语法:object.toString()
1 | var obj = new Object(); |
其他的类型作为Object的实例,都重写了toString方法:
1 | var arr = []; |
这里我们删除了arr的__proto__
上的toString方法,就会顺着原型链往上爬,寻找toString方法