属性描述对象

概述

属性描述对象,是用来描述一个对象的属性的行为,控制它的行为。

1
2
3
4
5
6
7
8
9
描述对象实例
{
value: 123, //存放属性值,默认undefined
writable: false, //存放布尔值,默认true,表示属性值是否可变
enumerable: true, //存放布尔值,表示属性是否可枚举,默认为true,如果为false,for...in和Object.keys()会跳过改属性
configurable: false, //存放布尔值,表示可配置性,默认为true。控制描述对象的可写性(value属性可改变)
get: undefined, //存放一个函数,表示该属性的取值函数(getter),默认undefined
set: undefined //存放一个函数,表示该属性的存值函数(setter),默认undefined
}
1
2
3
4
5
6
7
8
configurable属性为false,将无法删除该属性
var o =Object.defineProperty({},'p',{
value:123
})
delete o.p //false 无法删除,delete方法返回布尔值
Object.defineProperty(o,'p',{
value:243
}) //报错,不能重新定义p属性
Object.getOwnPropertyDescriptior

读出对象自身属性的属性描述对象

1
2
3
4
读取o对象的name属性的属性描述对象
var o ={name:'tom'}
Object.getOwnPropertyDescriptor(o,'name') //这里name是字符串
//{value: "tom", writable: true, enumerable: true, configurable: true}

#####Object.defineProperty(),Object.defineProperties()

该方法允许通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象。它的格式如下。这两个方法有性能损耗,不能大量使用

1
2
3
4
5
6
7
8
9
10
11
Object.defineProperty(object,propertyName,attributesObject)
----------
var o =Object.defineProperty({},'p',{
value:123,
writable:false,
enumerable:false,
configurable:false,
})
o.p //123
o.p=345
o.p=123 //因为writable为false,所以无法改变属性值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
##设置了get或着set,就不能设置writable属性和value属性
var o =Object.defineProperties({},{ //写法不同
p1:{value:1,enmuerable:true},
p2:{value:2},
p3:{writable:true},
p4:{
get:function(){return this.p1+this.p2},
configurable:true
}
})
o.p1 //1
o.p2 //2
o.p3 //3
Object.getOwnPropertyDescriptor(o,'p3')
//{value: undefined, writable: true, enumerable: false, configurable: false}
Object.defineProperty()方法它的writable、configurable、enumerable这三个属性的默认值都为false
可枚举性

只有可枚举属性,才会被for…in循环遍历,同时还规定原生继承的属性都是不可枚举的。

可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。具体来说,如果一个属性的enumerablefalse,下面三个操作不会取到该属性。

1
2
3
for...in 循环
Object.keys() 方法
JSON.stringify() 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#可以用enumerable:flase 来设置秘密属性
var o ={a:1,b:2}
Object.defineProperty(o,'c',{
value:3,
enumerable:false //默认就是false
})
o.c //3
-------
for(let x in o){
console.log(o[x])
}
//1 2
-------
Object.keys(o) //['a','b']
------
JSON.stringify(o) //"{"a":1,"b":2}"
可配置性configurable

当configurable为false时,value,writable,enumerable,configurable都不能修改了

  • writable从true改为false时是允许的,反过来就报错

    1
    2
    3
    4
    5
    var o = Object.defineProperty({}, 'p', {
    writable: true,
    configurable: false
    });
    Object.defineProperty(o,'p', {writable: false})
  • 至于value,只要writableconfigurable有一个为true,就允许改动。

    1
    2
    3
    4
    5
    6
    7
    var o2 = Object.defineProperty({}, 'p', {
    value: 1,
    writable: false,
    configurable: true
    });
    Object.defineProperty(o2,'p', {value: 2})
    o2.p //2
  • 用var声明变量时,configurable默认为flase,说明用var声明的变量不能用delete删除,而var声明对象就默认为true,可以用delete删除(delete只能删除对象的属性)

    1
    2
    3
    4
    5
    6
    7
    var a =2
    Object.getOwnPropertyDescriptor(this,'a')
    //{value: 2, writable: true, enumerable: true, configurable: false}
    --------
    var o={a:1}
    Object.getOwnPropertyDescriptor(o,'a')
    //{value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyNames()

Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。

1
2
3
4
5
6
7
8
9
10
11
12
var o =Object.defineProperties({},{
p1:{value:1,enumerable:true},
p2:{value:2,enumerable:false}
})
Object.getOwnPropertyNames(o)
//["p1", "p2"]
-------
Object.keys(o)
//['p1']
------------
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ] //系统原生属性都是不可枚举的(即非用户自定义)
Object.prototype.propertyIsEnumerable()

来判断一个属性是否可枚举

1
2
3
4
5
6
var o={p:123}
o.propertyIsEnumerable('p')
//ture
-------
o.propertyIsEnumerable('toString')
//false
存取器

存取器提供的是虚拟属性,即该属性的值不是实际存在的,而是每次读取时计算生成的。

注:取值函数getter不接受参数(对象也不能有与取值函数同名的属性),存值函数只接受一个参数(即属性的值)。

1
2
3
4
5
6
7
8
9
10
11
#对p属性取值时,取值函数会自动调用;对p属性赋值时,存值函数会自动调用。
var o ={
get p(){
return 'getter' //取值函数一般都是return
},
set p(value){
console.log('setter:'+ value)
}
}
o.p //getter 取值时调用
o.p = 123 //setter:123 赋值时调用
1
2
3
4
5
6
7
8
9
10
#数据对象和DOM对象的双向绑定
Object.defineProperty(user,'name',{
get:function(){
return document.getElementById('foo').value
},
set:function(newValue){
document.getElementById('foo').value=newValue
},
configurable:ture
})

上面就是mvvm框架的ViewModel业务逻辑。MVVM是Model-View-ViewModel的简写,视图(用户界面)和模型(数据)的双向映射。(缺点,用户频繁改动,cpu消耗很大)

Object.preventExtensions() & Object.isExtensible()

extension扩展,阻止扩展。使一个对象无法再添加新的属性(不能增加可删除)

extensible 可扩展的。检查是否可以为一个对象添加属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var o ={}
Object.preventExtensions(o)
Object.defineProperty(o,'p',{
value:2
})
//TypeError: Cannot define property p, object is not extensible
-----
Object.isExtensible(o) //false
------
o.p =1
o.p //undefined
-----------
#可以用delete删除一个现有属性
var o ={p:1}
Object.preventExtensions(o)
delete o.p //true
o.p //undefined
Object.seal() & Object.isSealed

seal:密封 ,既不能添加也不能删除旧属性,(本质就是把configurable改为false,所以writable可以从true改为false,但是反过来不行)

属性对象的value是由writable决定的

1
2
3
4
5
6
var o ={p:1}
Object.seal(o)
o.p =2
o.p //2
------
Object.isSealed(o) //true
Object.freeze() & Object.isFrozen()

不能添加,不能删除,不能更改。相当于固定住一个对象,变成常量。