JavaScript对象之数据属性与访问器属性

栏目: JavaScript · 发布时间: 5年前

内容简介:首先介绍了创建1.1

首先介绍了 JavaScript 对象数据属性与访问器属性的相关概念,然后介绍了属性定义与读取的相关方法,最后对 JavaScript 对象数据属性与访问器属性的知识做了一些扩展。

一. 创建JavaScript对象

创建 JavaScript 对简单的方法有两种:一是直接创建一个 object 实例,然后为他添加属性与方法,二是通过对象字面量语法的方式创建。

1.1 new object

var person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function(){
    alert(this.name);
};
复制代码

上述实例创建了一个名为person的实例对象,并为其添加了三个属性( nameagejob )和一个方法( sayName )。

1.2 对象字面量

上述示例同样可通过对象字面量的语法实现如下。

var person = {
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};
复制代码

二. 属性类型

对于 1.11.2 的创建的每个实例都有自己的属性和方法,这些属性在创建时都带有一些特征值,这些特征值仅供内部使用,在 JavaScript 中不能直接访问他们,按规定这些特征值需要放在两对方括号中,例如 [[Enumerable]]

ECMAScript 中有两类属性,分别是 数据属性选择器属性

1.1 数据属性

数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有 4 个描述其行为的 特性。

  • [[Configurable]] :表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。
  • [[Enumerable]] :表示能否通过for-in循环返回属性。
  • [[Writable]] :表示能否修改属性的值。
  • [[Value]] :包含这个属性的数据值。

通过 new object 或者对象字面量方式创建对象定义的属性,他们的 [[Configurable]][[Enumerable]][[Writable]] 特征均为 true ,而 [[Value]] 值被设置为指定的值。

var person = {
    name: "Nicholas"
}
复制代码

以上代码通过对象字面量的方式定义了一个 person 对象,并为它指定了 name 属性,此时 name 属性的四个特征值, [[Configurable]][[Enumerable]][[Writable]] 特征均为 true ,而 [[Value]]Nicholas

要修改属性默认的特性,必须使用Object.defineProperty()方法,可同时修改一个或多个特性值,该方法接收三个参数:

  • object :属性所在的对象
  • propertyName :属性的名字
  • descripor :属性的描述符,必须是 [[Enumerable]][[Writable]][[Value]] 中的一个
var person = {
    name: fanweiren
}; 
Object.defineProperty(person, "name", { 
 writable: false, 
 value: "Nicholas" 
}); 
alert(person.name); //"Nicholas" 
person.name = "Greg"; 
alert(person.name); //"Nicholas"
复制代码

以上代码将 name 属性的值设置为设置为 Nicholas ,并将 name 属性的 [[writable]] 特性值设为 false ,表示该属性只可读不可修改。如果尝试为它指定新值,非严格模式下,赋值操作会被忽略,在严格模式下,会抛出错误。

var person = {
    name: fanweiren
}; 
Object.defineProperty(person, "name", { 
 configurable: false, 
 value: "Nicholas" 
}); 
alert(person.name); //"Nicholas" 
delete person.name; 
alert(person.name); //"Nicholas"
复制代码

[[Configurable]] 特性设置为false后,属性 name 既不能从对象中删除,此时调用delete在非严格模式下什么也不会发生,在严格模式下会抛出错误。

一旦把 [[Configurable]] 特性设置为false即不可配置后,就不能在变回可配置了。且设置为false后, [[Enumerable]][[Writable]] 也都不能修改了。

发现一个奇怪的现象, [[Configurable]] 特性设置为 false 后,如果 [[Writable]] 以前为 true ,则还可以将其修改为 false ,如果 [[Writable]] 以前为 false ,则不可修改。

1.2 访问器属性

访问器属性不包含数据值;它们包含一对儿 gettersetter 函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下 4 个特性。

[[Configurable]]
[[Enumerable]]
[[Get]]
[[Set]]

访问器属性不能直接定义,必须使用 Object.defineProperty() 来定义。请看下面的例子。

var book = { 
 hideYear: 2004, 
 edition: 1 
}; 
Object.defineProperty(book, "year", { 
 get: function(){ 
 return this.hideYear; 
 }, 
 set: function(newValue){ 
 if (newValue > 2004) { 
 this.hideYear = newValue; 
 this.edition += newValue - 2004; 
 } 
 } 
}); 
book.year = 2005; 
alert(book.edition); //2
复制代码

以上代码定义了 hideYearedition 两个数据属性,同时定义了 year 这个访问器属性。 year 访问器属性包含 getset 两个方法, get 方法返回 hideYear 属性的值, set 方法通过计算来确定正确的版本。

三点总结:

  1. 所有直接通过 new object 或者对象字面量为对象添加的属性均为数据属性,访问器属性必须用 Object.defineProperty() 定义。
  2. 通过 new object 或者对象字面量为对象添加的属性,其 [[Configurable]][[Enumerable]][[Writable]] 属性默认均为 true ,通过 Object.defineProperty() 定义的属性,对于 defineProperty 方法没定义的特征,默认为 false
// 通过`new object`或者对象字面量为对象添加的属性
var person = {
    name: 'fanweiren'
} // configurable、enumerable、writable均为true

// 通过`Object.defineProperty()`定义的属性
Object.defineProperty(book, "name", {
    value: 'fanweiren'
} // configurable、enumerable、writable均为false

Object.defineProperty(book, "name", {
    configurable: true
    value: 'fanweiren'
}// configurable为true,enumerable、writable为false
复制代码
vue

三. 定义多个属性

利用 Object.defineProperty() 定义单个属性。利用 Object.defineProperties() 同时定义多个属性,该方法接收两个参数,具体使用方式见如下代码。

var book = {}; 
Object.defineProperties(book, { 
 _year: { 
    value: 2004 
 }, 
 edition: { 
    value: 1 
 }, 
 year: { 
     get: function(){
        return this._year; 
     }, 
     set: function(newValue){ 
        if (newValue > 2004) { 
             this._year = newValue; 
             this.edition += newValue - 2004; 
        } 
    } 
 } 
});
复制代码

以上代码为对象 book 定义了三个属性,其中 _yearedition 为数据属性, year 为访问器属性。

四. 读取数据的属性

Object.getOwnPropertyDescriptor() 方法可以取得给定属性的描述符。这个方法返回值是一个对象,如果是访问器属性,这个对象的属性有 configurableenumerablegetset ;如果是数据属性,这 个对象的属性有 configurableenumerablewritablevalue 。对于第三部分(定义多个属性)的代码,调用 Object.getOwnPropertyDescriptor() 方法后结果如下:

var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
console.log(JSON.stringify(descriptor))
//{"value":2004,"writable":false,"enumerable":false,"configurable":false}
alert(typeof descriptor.get);     //"undefined"

var descriptor = Object.getOwnPropertyDescriptor(book, "year");
console.log(JSON.stringify(descriptor)) // {"enumerable":false,"configurable":false}
alert(typeof descriptor.get); // function
alert(typeof descriptor.set); // function

复制代码

五. 总结

本文从对象的创建引出对象数据属性与访问器属性的概念,首先介绍了数据属性与访问器属性的相关知识,然后介绍了属性定义与读取的相关方法。主要结论如下:

  1. javascript 对象的属性分为数据属性与访问器属性两类,通过 new object 与对象字面量定义的属性都为数据属性,访问器属性必须通过 Object.defineProperty() 方法定义。
  2. 通过 new object 或者对象字面量为对象添加的属性,其 [[Configurable]][[Enumerable]][[Writable]] 属性默认均为 true ,通过 Object.defineProperty() 定义的属性,对于 defineProperty 方法没定义的特征,默认为 false
  3. 一个属性要么为数据属性,要么为访问器属性,不可能既是数据属性又是访问器属性。
  4. 访问器属性使用的常见方式,即设置一个值会导致其他属性发生变化,该思想是vue双向绑定数据实现的核心内涵。
  5. [[Configurable]] 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性, [[Enumerable]] 表示能否通过 for-in 循环返回属性。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hacking Growth

Hacking Growth

Sean Ellis、Morgan Brown / Crown Business / 2017-4-25 / USD 29.00

The definitive playbook by the pioneers of Growth Hacking, one of the hottest business methodologies in Silicon Valley and beyond. It seems hard to believe today, but there was a time when Airbnb w......一起来看看 《Hacking Growth》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具