zoukankan      html  css  js  c++  java
  • ES5 数据属性描述符和存取描述符

    一、数据属性描述符

    对象是一个属性集合,对象的基本特征是属性名(name)和属性值(value)。ES5 增加了属性描述符,可以更细腻的控制属性的不同操作。属性描述符有 configurable、writable 和 enumerable。

    属性描述符通常和 Object.defineProperty/Object.defineProperties 一起使用来定义属性,它也会受到诸如 Object.freeze/Object.seal 等方法改变。

    1. configurable 当且仅当 configurable 为 true 时,该属性才能够被改变,也能够被删除(delete),默认为 false

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	value: 'John'
    })
    // 不能 delete
    delete obj.name // false
    
    Object.defineProperty(obj, 'name', {
    	configurable: true,
    	value: 'John'
    })
    // 可以delete
    delete obj.name // true
    

    2. writable 当且仅当 writable 为 true 时,该属性才能被赋值运算符(=)改变,默认为 false

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	value: 'John'
    })
    obj.name = 'Backus' // 修改不起作用,仍然是 John,严格模式中会报错阻止修改
    
    Object.defineProperty(obj, 'name', {
    	writable: true,
    	value: 'John'
    })
    obj.name = 'Backus' // 被改为了 backus
    

    3. enumerable 当且仅当 enumerable 为 true 时,该属性才能够出现在对象的枚举属性(for in)中,默认为 false

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	value: 'John'
    })
    // 不能遍历
    for (var a in obj) {
    	console.log(a) // 无输出
    }
    
    Object.defineProperty(obj, 'name', {
    	enumerable: true,
    	value: 'John'
    })
    // 可以遍历
    for (var a in obj) {
    	console.log(a) // 输出 "name"
    }
    

    ES6 的 Object.keys 只返回 enumerable=true 的属性

    var obj = {name: 'John'}
    
    Object.defineProperty(obj, 'name', {
    	value: 'Backus',
    	enumerable: true
    })
    Object.defineProperty(obj, 'age', {
    	value: 30,
    	enumerable: false
    })
    
    Object.keys(obj) // ['name']
    

    可以通过 propertyIsEnumerable 方法判断属性的 enumerable 值

    obj.propertyIsEnumerable('name') // true
    obj.propertyIsEnumerable('age')  // false
    

    4. 使用 ES3(传统的) JSON 方式定义对象,其 configurable/writable/enumerable 默认都是 true,如下

    var obj = {name: 'John', age: 30}
    
    // configurable
    delete obj.name // true
    // writable
    obj.age = 32 // true
    // enumerable
    for (var a in obj) {
    	console.log(a) // age
    }
    
    

    也即

    var obj = {name: 'John', age: 30}
    

    等同于

    Object.defineProperty(obj, 'name', {
    	value: 'John',
    	configurable: true,
    	writable: true,
    	enumerable: true
    })
    Object.defineProperty(obj, 'age', {
    	value: 33,
    	configurable: true,
    	writable: true,
    	enumerable: true	
    })
    

      

    5. 使用 ES5 的 Object.defineProperty/Object.defineProperties 方式定义对象,其 configurable/writable/enumerable 默认都是 false,如下

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	value: 'John'
    })
    Object.defineProperty(obj, 'age', {
    	value: 33
    })
    
    // configurable
    delete obj.name // false
    // writable
    obj.age = 32 // false
    // enumerable
    for (var a in obj) {
    	console.log(a) // 无输出,不能遍历
    }
    

    也即

    Object.defineProperty(obj, 'name', {
    	value: 'John'
    })
    

    等同于

    Object.defineProperty(obj, 'name', {
    	value: 'John',
    	configurable: false,
    	writable: false,
    	enumerable: false		
    })
    

    数据属性描述符汇总如下

    二、存取属性描述符

    存取描述符是由一对 getter-setter 函数功能来描述的属性,格式为

    name: {
    	get: function() { ... },
    	set: function(newVal) { ... },
    	enumerable: true,
    	configurable: true
    }
    

    例如

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	configurable: true,
    	enumerable: true,
    	get: function() {
    		console.log('get')
    		return this.value
    	},
    	set: function(newVal) {
    		console.log('set')
    		this.value = newVal
    	}
    })
    
    // 赋值会调用 set 方法
    obj.name = 'John'
    // 取值会调用 get 方法
    obj.name
    

    与上述的属性描述符只能存在一种,即二选一,不能同时存在,否则会报错

    var obj = {}
    
    // 错误方式一
    Object.defineProperty(obj, 'name', {
    	value: 'John',
    	get: function() {
    		console.log('get')
    		return this.value
    	}
    })
    
    // 错误方式二
    Object.defineProperty(obj, 'name', {
    	writable: true,
    	get: function() {
    		console.log('get')
    		return this.value
    	}
    })
    

    Firefox 报错如下

    存取描述符汇总如下

    三、和属性描述符相关的几个函数

    1. Object.defineProperty
    2. Object.defineProperties
    3. Object.getOwnPropertyDescriptor

    Object.defineProperty 上面已经介绍过,Object.defineProperties 批量定制对象属性,内部其实循环方式调用 Object.defineProperty

    Object.defineProperties(obj, {
    	name: {
    		value: 'John',
    		writable: true
    	},
    	age: {
    		value: 30,
    		enmuerable: true
    	}
    })
    

    Object.getOwnPropertyDescriptor 返回该对象某属性的描述器,描述器自身是一个对象

    var obj = {}
    
    Object.defineProperty(obj, 'name', {
    	value: 'Backus',
    	writable: true,
    	enumerable: true
    })
    
    var des = Object.getOwnPropertyDescriptor(obj, 'name')
    console.log(des) 
    

    输出如图

  • 相关阅读:
    ajax专题
    luogu P1346 电车 最短路
    luogu P1462 通往奥格瑞玛的道路 最短路
    luogu P1328 生活大爆炸版石头剪刀布
    luogu P1315 联合权值 枚举
    luogu P1156 垃圾陷阱 背包问题
    luogu P1217 回文质数 枚举
    luogu P3650 滑雪课程设计 枚举
    luogu1209 修理牛棚 贪心
    luogu P1223 排队接水 贪心
  • 原文地址:https://www.cnblogs.com/snandy/p/5276578.html
Copyright © 2011-2022 走看看