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) 
    

    输出如图

  • 相关阅读:
    leetcode 122. Best Time to Buy and Sell Stock II
    leetcode 121. Best Time to Buy and Sell Stock
    python 集合(set)和字典(dictionary)的用法解析
    leetcode 53. Maximum Subarray
    leetcode 202. Happy Number
    leetcode 136.Single Number
    leetcode 703. Kth Largest Element in a Stream & c++ priority_queue & minHeap/maxHeap
    [leetcode]1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree
    正则表达式
    十种排序算法
  • 原文地址:https://www.cnblogs.com/snandy/p/5276578.html
Copyright © 2011-2022 走看看