浅谈js对象之数据属性、访问器属性、Object.defineProperty方法

一、对象

  这个不用多说,常见的几种创建对象的方法有:

  1.通过构造函数创建对象,如下所示:

 function Person(){

        }
 var person = new Person();

  2.通过Object创建简单对象,例如:

 var obj = new Object();

  3.通过字面量创建对象。

 var obj = {};

  常用的一般是第一种和第三种方法。

二、属性类型

  javascript中有两种属性:数据属性和访问器属性,确切的说这两种特性是用来描述对象属性的各种特征,比如说这个对象属性的值能否被改变,因为这些特性是内部值,而javascript又不能直接访问,所以在规范中把他们放在了两对儿化括号中,例如[[Enumerable]]。下面 来看看这两种具体的内部属性。

  1.数据属性

   数据属性包含一个数据值。在这个位置可以读取和写入值,

     [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性(这个后面会说),默认为true;

     [[Enumerable]]:用来修饰对象属性的枚举特性,表示能否通过用for in循环返回属性,默认为true;

     [[Writable]]:用来修饰对象属性值的可写特性,默认为true;

   [[Value]]:包含这个属性的数据值,访问器属性里面是没有这个特性的。默认为undefined;比如var person = {name:‘lili‘},这里设置了一个名叫name的属性,它的值是"lili", [[Value]]特性将被设置为"lili",其余的是三个特性都是默认值true。

  下面就用具体的实例来理解上面的特性。首先这里要先谈的是Object.defineProperty()方法,这个方法接收三个参数:属性所在的对象、属性的名字、和一个描述符对象(也就是上面的四个数据属性,用来描述对象属性的特性),这里要注意了,采用Object.defineProperty方法创建属性时候,数据属性[[configurable]]、[[writable]]、[[enumerable]]默认为false,这要和字面量直接声明属性时默认值相反但是如果只是用Object.defineProperty改变原来已有属性的值则没有此限制,具体看下面例子:

 var person = {};Object.defineProperty(person,‘name‘,{ //创建name属性
            value:‘lili‘,
        });
        console.log(person.name); //lili
        person.name = ‘shasha‘; //writable默认是false 不可改动属性值
        console.log(person.name); //lili

  修改writable的值为true可以看到,person.name的值打印出来是‘shasha‘;

 var person = {};
Object.defineProperty(person,‘name‘,{//创建name属性
            writable:true,
            value:‘lili‘,
        });
        console.log(person.name); //lili
        person.name = ‘shasha‘; //writable设置为true, 属性值被重写
        console.log(person.name); //shasha

 但是当person里面有属性,采用Object.defineProperty方法只是修改特性和值时,默认值都为true,具体请看下面示例:

    var person = {age:22};
        Object.defineProperty(person,‘age‘,{  //重新定义修改age属性
            value:33,
        });
        person.age = 66;
        console.log(person.age); //66  说明writable此时为true,

  设置[[enumrable]]特性的规则跟[[writable]]相同,为true时才能用for in 循环遍历出属性。下面来重点看看[[Configurable]]特性的作用,例子如下:

   var person = {};
        Object.defineProperty(person,‘name‘,{
            configurable:false,
            value:‘lili‘,
        });
        console.log(person.name); //lili
        delete person.name;
        console.log(person.name); //lili

  把configurable设置为false,表示不能删除对象属性,对这个这个属性调用delete方法,非严格模式下什么也不会发生,严格模式下则会抛出错误,而且一旦把属性从configurable设置为false,以后就不能把它设置为true,此时在调用Object.defineProperty方法修改除writable、value之外的特性,都会导致错误,看下面例子:

   var person = {};
        Object.defineProperty(person, ‘name‘, {
            configurable: false,
            enumerable: true,
            writable: true,
            value: ‘lili‘,
        });
        Object.defineProperty(person, ‘name‘, {
            // configurable: true,  //会报错额!
            // enumerable: false,  //会报错的!
            writable: false,
            value: ‘tangtang‘,
        });
        person.name = ‘wangdachui‘;
        console.log(person.name);//tangtang

  2.访问器属性

  访问器属性不包括数据值,它包含一对getter和setter函数,在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,访问器属性有如下四个特性:

   [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为数据属性(这个后面会说),默认为true;

  [[Enumerable]]:用来修饰对象属性的枚举特性,表示能否通过用for in循环返回属性,默认为true;

   [[Get]]:在读取属性时候调用的函数,默认为undeifne;

   [[Set]]:在写入属性时候调用的函数,默认为undeifne;

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

   var book = {
            _year: 2018,
            edition: 1,
        };
        Object.defineProperty(book, ‘year‘, {
            get: function () {
                alert(‘通过对象方法访问 哈哈!‘);
                return this._year;
            },
            set: function (newValue) {
                if (newValue > 2004) {
                    this._year = newValue;
                    this.edition += newValue - 2004;
                    alert(this.edition);
                }
            }
        });
        console.log(book.year) //通过对象方法访问 get函数里面alert出对应信息;
        book.year = 2005;
        console.log(book.edition); //2

  以上例子中,book对象有两个默认属性:_year 和 edition ,其中_year前面加了下划线,用于表示只能通过对象方法去访问这个属性,即通过get方法返回属性值。如果直接访问book.edition的值,则不会调用get方法返回。book.year=2005即是修改book的year属性值,会调用set方法,参数newValue就是设置的2005这个值,在上面例子中set函数里还改变了属性edition的值。

3.定义多个属性

  采用Object.defineProperties我们也可以为一个对象定义多个属性,这个方法有两个参数:第一个要定义属性的对象,第二个也是对象,表示要添加的多个属性和其对应的属性描述符,具体怎么添加呢,请看下面的例子:

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

  以上代码在book对象上定义了两个数据属性(_year和edition)和一个访问器属性(year)。

  4.读取属性的特性

  上面我们一直是在讨论如何设置属性的描述特性,那么对于数据属性和访问器属性里面的具体特性我们怎么读取呢?这里介绍另一个Object的方法:getOwnPropertyDescriptor方法,该方法接收两个参数:属性所在的对象和要读取其描述符的属性名称,它的返回是一个对象,来我们来看看具体的实例:

  var book = {};
        Object.defineProperties(book, {
            _year: {
                writable: true,
                value: 2004,
            },
            edition: {
                writable: true,
                value: 1,
            },
            year: {
                get: function () {
                    return this._year;
                },
                set: function (newValue) {
                    if (newValue > 2004) {
                        this._year = newValue;
                        this.edition += newValue - 2004;
                    }
                }
            }
        });
        book.year = 2005;
        console.log(book.edition); //2
        var descriptor1 = Object.getOwnPropertyDescriptor(book, ‘_year‘);
        console.log(descriptor1.value); //2005
        console.log(descriptor1.configurable);//false
        console.log(typeof descriptor1.get); //undefine
        var descriptor2 = Object.getOwnPropertyDescriptor(book, ‘year‘);
        console.log(descriptor2.value); //2005
        console.log(descriptor2.configurable);//false
        console.log(typeof descriptor2.get); //function;

  

  

  

  

  

原文地址:https://www.cnblogs.com/homeStrong/p/8836823.html

时间: 2024-08-05 17:09:35

浅谈js对象之数据属性、访问器属性、Object.defineProperty方法的相关文章

浅谈 js 对象 toJSON 方法

前些天在<浅谈 JSON.stringify 方法>说了他的正确使用姿势,今天来说下 toJSON 方法吧.其实我觉得这货跟 toString 一个道理,他是给 stringify 方法字符串化的时候调用的.看下 MDN 官方文档吧<toJSON behavior>.非常简单,但是要注意的是他和 stringify 方法第二个参数稍微有点不同.因为 stringify 第二个参数是回调函数时,只是对当前 key 对应的值进行修改.而 toJSON 则是对当前对象进行修改.例如: v

JavaScript 属性类型(数据属性 访问器属性)

ECMA-2把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.” 严格来说,这就相当于说对象是一组没有特定顺序的值.对象的属性或方法都有一个名字,而每个名字映射到一个值.我们可以把ECMAScript的对象想象成散列表,无非就是一组名值对,其中值可以是数据或函数.(高程三 P139) [译]JavaScript中对象的属性   <高程三 P139 属性类型> JavaScript笔记--数据属性和访问器属性 JavaScript中有两种不同类型的属性:命名数据属性(named

浅谈Js对象的概念、创建、调用、删除、修改!

一.我们经常困惑,对象究竟是什么,其实这是一种思维,一种意识上的东西,就像我们都说    世界是有物质组成的道理一样,理解了下面的几句话!对象也不是那么抽象!    1.javascript中的所有事物都是对象,字符串.数值.数组.函数!    而且js还允许自定义对象!    2.对象就只是带有属性和方法的特殊数据类型    3.属性是与对象相关的值,方法是能够在对象上执行的动作! 其实在这里的时候我们应该就有一个疑问要解决了,我们说函数是一个对象,为什么?    很简单,js中所有的事物都是

Js中的数据属性和访问器属性

Js中的数据属性和访问器属性 在javaScript中,对象的属性分为两种类型:数据属性和访问器属性. 一.数据属性 1.数据属性:它包含的是一个数据值的位置,在这可以对数据值进行读写. 2.数据属性包含四个特性,分别是: configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为true enumerable:表示能否通过for-in循环返回属性 writable:表示能否修改属性的值 value:包含该属性的数据值.默

js高级程序设计——数据属性和访问器属性

ES5中对象的属性可以分为"数据属性"和"访问器属性"两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性分为 configurable   enumerable writable value 解释:configurable: 表示能否通过delete删除属性重而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性. enumerable:表示能否通过for-in循环返回属性. writable:表示

关于对象的数据属性和访问器属性

ECMAScript中有两种属性:数据属性和访问器属性. 数据属性: 数据属性包含一个数据值的位置,在这个位置可以读取和写入值.数据属性有4个描述其行为的特性. 1. [[Configurable]] 2. [[Enumerable]] 3. [[Writable]] 4. [[Value]] 要修改属性默认的特性,必须使用 Object.defineProperty()方法.这个方法接收三个参数,属性所在的对象,属性的名字和一个描述符对象.其中,描述符对象的属性必须是:configurable

js中的访问器属性中的getter和setter函数实现数据双向绑定

嗯,之前在读js红宝书的时候,在对象那一章有介绍属性类型.第一种数据类型指的是数据属性,第二种是访问器属性.在初识vue的时候,其双向数据绑定也是基于访问器属性中的getter和setter函数原理来实现的.本篇文章就着重解析这两个函数的工作原理. 首先,我们先创建一个a对象,并给他定义了一个默认的属性_b,_b前面的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性. var a={ _b=5;}; 接着定义一个属性为'c'的访问器属性,该属性包含一个get和set函数,get函数用来

JavaScript | 数据属性与访问器属性

属性类型 数据属性 - 包含一个数据值的位置,可以读取和写入值 [writable] 是否能修改属性的值 true [enumerable] 是否通过for in 循环返回属性(是否可以被枚举) true [configurable] 是否能通过delete删除,能否修改属性的特性,能否修改访问器属性 true [value] 包含这个属性的数据值,读取属性值的时候从这个位置读取. undefined 访问器属性 [enumerable] 是否通过for in 循环返回属性(是否可以被枚举) t

浅谈js中的this关键字

浅谈js中的this关键字 全局作用域中的this 函数作用域中的this 不同函数调用方法下的this 直接调用 作为对象的方法调用 作为构造函数调用 通过call或apply方法调用 嵌套函数作用域中的this 浅谈js中的this关键字 this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要.接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示,权当交流之用. 全局作用域中的this 本文将以作用域由