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 循环返回属性。

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

查看所有标签

猜你喜欢:

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

程序设计实践

程序设计实践

[美] Brian W. Kernighan、Rob Pike / 裘宗燕 / 机械工业出版社 / 2000-8 / 20.00元

这本书从排错、测试、性能、可移植性、设计、界面、风格和记法等方面,讨论了程序设计中实际的、又是非常深刻和具有广泛意义的思想、技术和方法。一起来看看 《程序设计实践》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具