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) 
    

    输出如图

  • 相关阅读:
    鸟哥的linux私房菜学习-(八)Linux 文件与目录管理
    我的作品
    聊聊软件测试面试的一些事
    如何做一名专业的软件测试工程师
    测试Leader应该做哪些事
    软件测试工程师的岗位职责
    一个完整的性能测试流程
    做接口测试需要哪些技能
    软件质量保障体系建设
    性能测试常见瓶颈分析及调优方法
  • 原文地址:https://www.cnblogs.com/snandy/p/5276578.html
Copyright © 2011-2022 走看看