资讯专栏INFORMATION COLUMN

JavaScript Object.defineProperty()学习笔记。

lushan / 1759人阅读

摘要:数据属性有个描述其行为的特性。表示能否通过删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。表示能否修改属性的值。其中,描述符对象的属性必须是和。返回值被传递给函数的对象。

属性类型

ECMAScript中有两种属性:数据属性和访问器属性。
数据属性:
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性。

[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。在对象上直接定义的属性,它们的这个特性默认值为true。
[[Enumerable]]:表示能否通过for-in循环返回属性。在对象上直接定义的属性,它们的这个特性默认值为true。
[[Writable]]:表示能否修改属性的值。在对象上直接定义的属性,它们的这个特性默认为true.
[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。这个特性的默认值为undefined。

要修改属性默认的特性,必须使用ECMAScript5的Object.defineProperty()方法。这个方法接受三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable和value。设置其中的一个或多个值,可以修改对应的特性值。例如:

var person = {};
Obejct.defineproperty(person,"name",{
    writable:false,
    value:"Nics"
})
console.log(person.name)//Nics
person.name = "tom";
console.log(person.name)//Nics

这个例子创建了一个明为name的属性,它的值是只读的,如果为它指定新的值,在非严格模式下,赋值操作将被忽略;在严格模式下赋值操作将会抛出错误。
如果把configurable设置为false,表示不能从对象中删除属性,而且一旦把属性定义为不可配置的,就不能再把它变为可配置了。此时再调用Object.defineProperty()方法修改writable之外的特性都会抛出错误。
也就是说,可以多次调用Object.defineProperty()方法修改同一个属性,但在把configurable特性设置为false之后就会有限制了。
再调用Object.defineProperty()方法创建一个新的属性的时候,如果不指定configurable、enumerable、writable特性的默认值都是false。
Obejct.defineProperty(obj,prop,descriptor)方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
参数:

obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptor:将被定义或修改的属性描述符。

返回值:

被传递给函数的对象。

属性描述符:

configurable:当且仅当改属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false。
enumerable:当且仅当改属性的enumerable为true时,改属性才能够出现在对象的枚举属性中。默认为false。
数据描述符同时具有以下可选键值:
value:该属性对应的值。可以是任何有效的JavaScript值(数值,对象,函数等)。默认为undefined。
writable:当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为false。
存取描述符同时具有以下可选键值:
get:一个给属性提供getter的方法,如果没有getter则为undefined。当访问改属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)默认为undefined。
set:一个给属性提供setter的方法,如果没有setter则为undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即改属性新的参数值。
var o = {}
//在对象中添加一个属性与数据描述符的示例。
Obejct.defineProperty(o,"a",{
    value:37,
    writable:true,
    enumerable:true,
    configurable:true
})
//对象o拥有了属性a,值为37

//在对象中添加一个属性与存取描述符的示例。
var bValue;
Obejct.defineProperyty(o,"b",{
    get:function(){
        return bValue;
    },
    set:function(newValue){
        bValue = newValue;
    },
    enumerable:true,
    configurable:true
})
o.b = 38;
//对象o拥有了属性b,值为38.
//数据描述符和存取描述符不能混合使用。

一般的Setters和Getters
下面的例子展示了如何实现一个自存档对象。当设置temperature属性时,archive数组会获取日志条目。

function Archiver(){
    var temperatrue = null;
    var aechive = [];
    Obejct.defineProperty(this,"temperatrue",{
        get:function(){
            console.log("get!");
            return temperature;
        },
        set:function(value){
            temperature = value;
            archive.push({val:temperature})
        }
    });
    this.getArchive = function(){return archive}
}
var arc = new Archiver();
arc.temperature;//"get!";
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive();//[{val:11},{val:13}]

或:

var pattern = {
    get:function(){
        return "I alway return this string,whatever you have assigned"
    },
    set:function(){
        this.myname = "this is my name string"
    }
}
function TestDefineSetAndGet(){
    Object.defineProperty(this,"myproperty",pattern);
}
var instance = new TestDefineSetAndGet();
instance.myproperty = "test";
console.log(instance.myproperty);
console.log(instance.myname)

如果访问者的属性是被继承的,他的get和set方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。

function myclass(){}
var value;
Obejct.defineProperty(myclass.prototype,"x",{
    get(){
        return value;
    },
    set(x){
        value = x;
    }
})
var a = new myclass();
var b = new myclass();
a.x=1;
console.log(b.x);//1

在get和set方法中,this指向某个被访问和修改属性的对象。

function myclass(){}
Obejct.defineProperty(myclass.prototype,"x",{
    get(){
        return this.stored_x;
    },
    set(x){
        this.stored_x = x;
    }
});
var a = new myclass();
var b = new myclass();
a.x=1;
console.log(b.x)//undefined

不像访问者属性,值属性始终在对象自身上设置,而不是一个原型。然而,如果一个不可写的属性被继承,它仍然可以防止修改对象的属性。

function myclass() {
}
myclass.prototype.x = 1;
Object.defineProperty(myclass.prototype, "y", {
  writable: false,
  value: 1
});
var a = new myclass();
a.x = 2;
console.log(a.x); // 2
console.log(myclass.prototype.x); // 1
a.y = 2; // Ignored, throws in strict mode
console.log(a.y); // 1
console.log(myclass.prototype.y); // 1

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102797.html

相关文章

  • 对象管理器(defineProperty学习笔记

    摘要:通过设置我们可以将一些属性锁定,来防止别人的修改,这是一种防御编程形式,就像语言的内置对象一样不过的内置对象都可以被随意更改。可以使用来判断某一个属性是否可以枚举。 对象管理器(defineProperty) 在 JavaScript 里面声明一个变量,通常我们有三种方式可以实现: let person = {} // 对象字面量 let cat = new Objec...

    mist14 评论0 收藏0
  • 《你不知道的javascript笔记_对象&原型

    摘要:上一篇你不知道的笔记写在前面这是年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响年是向上的一年在新的城市稳定连续坚持健身三个月早睡早起游戏时间大大缩减,学会生活。 上一篇:《你不知道的javascript》笔记_this 写在前面 这是2019年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响2018年是向上的一年:在新的城市稳定、...

    seasonley 评论0 收藏0
  • JavaScript学习第七天笔记(面向对象)

    摘要:面向对象概述面向对象编程的全称是简称为。面向对象编程是用抽象方式创建给予现实世界模型的一种编程模式。构造函数构造函数又被称为构造器或对象模板,是创建对象的一个方法。 面向对象 概述 面向对象编程的全称是Object Oriented Programming,简称为OOP。面向对象编程是用抽象方式创建给予现实世界模型的一种编程模式。面向对象编程可以面向对象编程的三个主要特征是:1.封装 ...

    Tychio 评论0 收藏0
  • JavaScript学习笔记整理:对象篇

    摘要:函数式对象的一个子类型,中的函数是一等公民内置对象中还有一些对象子类型,通常被称为内置对象。内容对象的内容是由一些存储在特定命名位置的任意类型的值组成的,我们称之为属性。 语法 对象两种定义形式 声明(文字)形式 构造形式 //声明(文字)形式 var myObj = { key: value // ... } //构造形式 var myObj = new Ob...

    testbird 评论0 收藏0
  • javascript高级程序设计》笔记:对象数据属性和访问器属性

    摘要:枚举对象的属性第二种情况设置为,可以被枚举。内置对象访问器属性方法介绍摘自方法返回指定对象上一个自有属性对应的属性描述符。对象中存在的属性描述符主要有数据描述符和访问器描述符两种返回传递给函数的对象参考中的 1. 什么是对象 对象是无序属性的集合 创建自定义对象最简单的方式就是以字面量的形式创建对象(或创建一个Object实例),然后再为它添加属性和方法,如下所示: var perso...

    mating 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<