js权威指南就学笔记,第四章面向对象的主次设计

写在前头

注:那么些体系是自个儿对js知识的片段梳理,当中不少剧情出自书籍:Javascript高端程序设计第三版和JavaScript权威指南第4版,谢谢它们的撰稿人和翻译。有察觉什么难题的,欢迎留言建议。

知情对象

1、创设对象

面向对象(Object-Oriented,OO)的语言有二个标识,这正是它们都有类的概念,而经过类能够创设任意四个有着同等属性和措施的对象.

一.数据属性

多少属性的陆个特点:

  • Configurable:一意味着能或不能够通过delete删除属性从而再度定义,二是还是不是修改属性的个性,三能还是不可能把质量修改为访问器属性。对象直接量里暗中认可值true。
  • Enumerable:表示能不能够通过for-in循环重临属性。对象直接量里默许值true。
  • Writable:表示是还是不是修改属性的值。对象直接量里私下认可值true。
  • Value:包蕴那么些天性的数据值。对象直接量里暗中认可值undefined。

//查看对象直接量的属性的属性特性默认值
var people = {
    name:'jaychou',
    sayName:function () {
        console.log(this.name);
    }
};
/**{value: "jaychou", writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'name'));
/**{value: ƒ, writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'sayName'));
//getOwnPropertyDescriptor对于继承属性和不存在的属性,返回undefined

要修改属性私下认可的性格,使用Object.defineProperty()方法,接收3个参数:对象,属性名字和讲述符对象。

//修改属性默认特性:
Object.defineProperty(person,'job',{
    emumerable:false,//不可枚举
    value:'singer',
    writable:false,//不可写
    configurable:true
});
/**{name: "jaychou", sayName: ƒ, job: "singer"}*/
console.log(person);
for(var prop in person){
    //打印name,sayName
    console.log(prop);
}
//会报错
try{
    person.job = 'director';
}catch (e) {
    //Cannot assign to read only property 'job' of object
    console.log(e);
}

能够频仍调用Object.defineProperty()方法修改同二特性质,但在把configurable天性设置为false之后就会有限制了:

Object.defineProperty(person,'height',{
    configurable:false,//不可配置
    writable:true,
    value:172
});
try{
    Object.defineProperty(person,'height',{
        configurable:true,//出错
        enumerable:true,//出错
        value:175,//正常
        writable:false,//writable从true变false可以,false变true也会出错
    });
}catch (e) {
    //Cannot redefine property: height at Function.defineProperty
    console.log(e);
}
try{
    delete person.height;
}catch (e) {
    //设置成不可配置后也不可删除:Cannot delete property 'height' of #<Object>
    console.log(e);
}

其它,调用
Object.defineProperty()方法时,固然不钦赐,configurable、enumerable 和
writable 特性的暗中同意值都是 false。假诺是修改已有总体性,则无此限制。


(一)、通过对象直接量的不二等秘书诀开创

ECMAScript中未有类的概念,因而它的目的也与基于类的语言中的对象有所分裂.

2.储存器属性

储存器属性不带有数据值,只含有包涵 getter 和 setter 函数(非必需)。
在读取存款和储蓄器属性时,会调用 getter
函数,那一个函数负责重临有效的值;在写入存款和储蓄器属性时,会调用 setter
函数并传播新值,那几个函数负责调节哪些处理数量。5个属性脾性如下:

  • Configurable:壹意味是还是不是通过delete删除属性从而再度定义,贰是否修改属性的风味,三是还是不是把品质修改为多少属性。对象直接量的暗许值true
  • Enumerable:表示是不是通过for-in循环再次回到属性。对象直接量的私下认可值true
  • Get:在读取属性时调用的函数。对象直接量私下认可值undefined
  • Set:在写入属性时调用的函数。对象直接量的暗中同意值undefined

概念存款和储蓄器属性最简便的方法是运用对象直接量语法的开始展览写法:

var p = {
    x:3.0,
    y:4.0,
    //r是可读写的存取器属性
    get r(){return Math.sqrt(this.x*this.x+this.y*this.y);},
    set r(newValue){
        var oldvalue = Math.sqrt(this.x*this.x+this.y*this.y);
        var ratio = newValue/oldvalue;
        this.x *= ratio;
        this.y *= ratio;
    },
    //theta是只读存取器属性
    get theta(){return Math.atan2(this.y,this.x);}
}
console.log(p.r);
p.r = 25;

使用Object.defineProperty()方法定义存款和储蓄器属性:

var book = {
    _year:2004,
    edition:1
};
Object.defineProperty(book,"year",{
    get:function () { return this._year; },
    set:function (newValue) {
        if(newValue>2004){
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
})
/**{get: ƒ, set: ƒ, enumerable: false, configurable: false}*/
console.log(Object.getOwnPropertyDescriptor(book,'year'));

如例子所示,使用存款和储蓄器属性的科学普及格局,即设置1个属性的值会促成其余质量发生变化。还有1种常见就是当今流行的接近于Vue的响应式原理,就是把data中的属性都选用defineProperty修改为存款和储蓄器属性,能够监听到数量的变迁。

始建自定义对象的最简便易行方法正是创办二个Object的实例,然后再为它增多属性和方式

表达:对象直接量是由若干名/值对构成的映射表,名/值对中级用冒号分隔,名/值对里面用逗号分隔,整个映射表用花括号括起来。

ECMA-26二把对象定义为:”冬天属性的集结,其性子能够分包基本值,对象大概函数”.

叁.定义几个性情

每每要成立或退换几性情子,那时候能够应用Object.defineProperties()方法,它接受三个参数,要抬高或修改属性的对象和叁个映射表,包蕴名称和总体性描述符。

var book1 = {};
Object.defineProperties(book1,{
   _year:{
       value:'2008'
   },
   editor:{
       enumerable:true,
       value:'2'
   },
   year:{
       get:function () {
           return this._year;
       },
       set:function (newValue) {
           this._year = newValue;
           this.edition += newValue - 2004;
       }
   }
});
1     var person = new Object();
2     person.name = "Nicholas";
3     person.age = 29;
4     person.job = "SoftWare Engineer";
5     person.sayName = function(){
6         alert(this.name);
7     };

如:

严酷来讲,那就一定于说对象是一组并没有一定顺序的值.对象的各类属性或艺术都有3个名字,而各样名字都映射到一个值.正因为这么,我们能够把EMCAScript的靶子想象成散列表:无非就是1组名值对,在那之中值能够是数量或函数.

四.指标的可扩张性

对象的可拓展性表示是不是足以给目标增添新属性。全数内置对象和自定义对象都以显式可扩充的,宿主对象的可扩充性是由Javascript引擎定义的。

 

 

种种对象老师基于三个引用类型创立的,这几个引用类型能够是事先研究的原生类型,也能够是开拓职员定义的类型.

一.询问对象可拓展性
var teacher = {age:25};
//true:代表可拓展
console.log(Object.isExtensible(teacher));

创建对象的首荐方式是目的字面量情势

 

陆.1 了解对象

二.转换为不可拓展(“锁定目的”)
Object.preventExtensions(teacher);
//false
console.log(Object.isExtensible(teacher));
try{
    teacher.subject = 'math';
}catch (e) {
    //TypeError: Cannot add property subject, object is not extensible
    console.log(e);
}

转变来不可拓展的操作是不可逆的,而且只好影响到对象自笔者的可拓展性,要是给贰个不足拓展目的的原型增多属性,那个不可拓展目的一样会继续那些新属性。

1     var person = {
2         name: "Nicholas",
3         age: 29,
4         job: "SoftWare Engineer",
5         sayName: function(){
6             alert(this.name);
7         }
8     };

 

创制自定义对象的最简易就是创制三个Object的实例,然后再为它增多属性和方法.

伍.密封目的

密封对象比锁定指标更高一层,除了不足拓展以外,对象的兼具本人性质都设置成了不足配置的。一样密封对象操作是不可逆的。

var tea1 = {subject:'math'};
//false:代表未密封
console.log(Object.isSealed(tea1));
Object.seal(tea1);
try{
    Object.defineProperty(tea1,'subject',{
        //enumerable:false,//出错
        //configurable:true,//出错
        writable:false//和上面说的一样,writable从true变成false可以,false变成true则出错
    });
}catch (e) {
    console.log('出错..');
    console.log(e);
}
//true:已密封
console.log(Object.isSealed(tea1));

 

 

var person=new Object();
    person.name="Nicholas";
    person.age=29;
    person.job="Software Engineer";

    person.sayName=function(){
        alert(this.name);
    };

陆.冰冻对象

冻结比密封对象多的法力是:可以将它自有的具有数据属性设置为只读(如果指标的存取器属性具备setter方法,存取器属性将不受影响,还是可以够经过给属性赋值调用它们)。

var tea2 = {subject:'Chinese'};
//false:代表未冻结
console.log(Object.isFrozen(tea2));
Object.freeze(tea2);
try{
    tea2.subject = 'math';
}catch (e) {
    //TypeError: Cannot assign to read only property 'subject' of object
    console.log(e);
}
//true:已冻结
console.log(Object.isFrozen(tea2));

质量类型

5

早期职员每每利用那种创立贰个名对象,并为它增加多少个属性和方法.之后,对象字面量成为开创那种对象的首荐形式.

7.属性性情规则计算

  • 尽管目的是不可拓展的,则能够编写已有个别自有总体性,但无法给它助长新属性。
  • 1旦属性是不足配置的,则不能够改改它的可配置性和可枚举性。
  • 借使存取器属性是不可配置的,则不能改改其getter和setter方法,也无法将它调换为数据属性。
  • 要是数额属性是不足配置的,则不可能将它调换为存取器属性。
  • 要是数据属性是不可配置的,则不可能将它的可写性从false修改为true,但能够从true修改为false。
  • 1经数量属性是不可配置且不得写的,则无法修改它的值。不过可配备但不足写属性的值是足以修改的(做法:先将它标识为可写的,然后修改它的值,最后调换为不可写的)。

 

5

var person={
        name:"Nicholas",
        age:29,
        job:"Software Engineer",

        sayName:function(){
            alert(this.name);
        }

 

其一例子中的person对象与前边例子中的person对象同样的,都有平等的性子和方法.这个属性在成立时都包含壹些特征值(characteristic),JavaScript通过这几个特征值来定义它们的行为.

 

 

陆.一.1质量类型

里头属性无法直接待上访问,ECMAScript伍把它们放在两对方括号中,分为数据属性和走访器属性

 

ECMA-262第4版在概念唯有个中都用的特色(attribute)时,描述了品质(property)的各类特征.ECMA-26贰概念这么些特色是为了落到实处JavaScript引擎用的,因而在JavaScript中不能够直接待上访问它们.为了表示特征是中间值,该标准把它们位于了两对儿方括号中,例如[[Enumerable]].

一、数据属性

 

ECMAScript中有三种属性:数据属性和做客器属性.

多少属性包涵二个数据值的职务。在这么些任务可以读取和写入值。数据属性有伍个描述其行事的表征

 

壹.数额属性

[[Configurable]]:表示是还是不是通过delete输出属性从而定义属性,能否修改属性的风味,只怕是不是把品质修改为访问器属性,默许值为true

1

数据属性包蕴四个数据值的地点.在这些职位能够读取和写入值.数据属性有6个描述其一举一动的特性.

[[Enumerable]]:表示能不可能通过for-in循环再次回到属性,暗许值为true

var empty = {}; //创建一个空对象

[[Configurable]]:表示能或无法通过delete删除属性从而再一次定义属性,能或无法修改属性的表征,或然是还是不是把品质修改为访问器属性.像前边例子中那么直接在指标上定义的性质,它们那些特点私下认可值为true.

[[Writable]]:表示是否通过退换属性的值,私下认可值为true

2

[[Enumerable]]:表示是不是通过for-in循环再次回到属性.像前边例子中那么直接在对象上定义的属性,它们的那天性格暗中认可值为true.

[[js权威指南就学笔记,第四章面向对象的主次设计。Value]]:包罗那特性情的数据值,读取属性值的时候,从那些地点读;写入属性值的时候,把新值保存在这些岗位

var point = {

[[Writable]]:表示是或不是修改属性的值.像前面例子中那样直接在指标上定义的品质,它们的这些天性私下认可值为true.

 

3

[[Value]]:包罗这么些天性的数码值.读取属性值的时候,从这么些职位读;写入属性值的时候,把新值保存在那些地方,这么些特点的暗许值为undefined.

要修改属性暗中认可的性格,必须使用ECMAScript5的Object.defineProperty()那一个方法.那几个点子接受多少个参数:属性所在的靶子、属性的名字和2个叙述符对象

    x : 0,

对此像前面包车型大巴事例中那样直接在对象上定义的性情,它们的[[Configurable]],[[Enumberable]]和[[Writable]]特色都被安装为true,而[[Value]]特点被设置为钦命的值.

 

4

var person={
        name:"Nicholas"
    };
1     var person = {};
2     Object.defineProperty(person,"name",{
3         writable: false,//设置为不可修改属性的值
4         value: "Nicholas"
5     });
6 
7     console.log(person.name); // " Nicholas"
8     person.name = "Oreg";
9     console.log(person.name); // " Nicholas"
    y : "ccc

此处开创了1个名字为name的性质,为它内定的值为”Nicolas”.也正是说,[[Value]]特征将被安装为”Nicolas”,而对这么些值的其余改造都将反映在那些地点.

 

5

要修改属性暗中认可的性状,必须使用ECMAScript
5的Object.defineProperty()方法.这么些主意接收多少个参数:属性所在的对象,属性的名字和八个讲述符对象.当中,描述符(descriptor)对象的质量必须是:configurable,enumerable,writable和value.设置个中的三个或多个值,能够修改对应的表征值.

 

}
var person={};
    Object.defineProperty(person,"name",{
        writable:false,
        value:"Nicholas"
    });

    alert(person.name);//Nicholas
    person.name="Greg";
    alert(person.name);//Nicholas

把donfigurable设置为false,表示不可能从指标中剔除属性。一旦把质量定义为不可配置的,就不可能再把它变回可计划的了。此时,在调用Object.defineProperty()方法修改处writable之外的性状,都会促成错误

 

本条例子创造了二个名称为name的性质,它的值”Nicolas”是只读的.那性子格的值是不足修改的,若是尝试为它钦赐新值,则在非严酷格局下,赋值操作将被忽视;在从严形式下,赋值操作将会产生抛出错误.

 1     var person = {};
 2     Object.defineProperty(person,"name",{
 3         configurable: false,
 4         value: "Nicholas"
 5     });
 6 
 7     //抛出错误
 8     Object.defineProperty(person,"name",{
 9         configurable: true,
10         value:"Nicholas"
11     });

 

恍如的平整也适用于不可配置的属性.

 

指标直接量是三个表明式,每一回运算都会创设并初阶化三个新的靶子。

var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:"Nicholas"
    });

    alert(person.name);//Nicholas
    delete person.name;
    alert(person.name);//Nicholas

在调用Object.defineProperty()方法时,假设不点名,configurable、enumerable和writable特性的暗许值都是false

(二)、通过new创造对象

把configurable设置为false,表示不能够从目的中删去属性.倘使对这么些天性调用delete,则在非严厉形式下什么也不会爆发,而在严苛方式下会招致错误.而且,1旦把品质定义为不可配置的,就不能再把它变回可安插了.此时,再调用Object.defineProperty()方法修改除writable之外的性状,都会导致错误:

 

new运算符创立并开端化1个新目的。关键字new后紧跟着3个函数调用。这里的函数称作构造函数(constructor),构造函数用于初叶化1个新创制的对象。

var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:"Nicholas"
    });

    Object.defineProperty(person,"name",{//Uncaught TypeError: Cannot redefine property: name
        configurable:true,
        value:"Nicholas"
    });

二、访问器属性

如:

也等于说,能够屡屡调用Object.defineProperty()方法修改同一属性,但把configurable天性设置为false之后就会有限制了.

做客器属性不含有属性值;他们带有1对儿getter和setter函数,在读取访问器属性时,会调用setter函数,这几个函数负责再次来到有效的值,在写入访问器属性时,会调用getter函数,并传到新值,那个函数决定怎么样处理数量。访问器属性有如下5个性子

 

在调用Object.defineProperty()方法时,假如不钦定,configurable,enumerable和writable特性的默许值都以false.

[[Configurable]]:表示是或不是通过delete输出属性从而定义属性,能或无法修改属性的特色,恐怕是还是不是把品质修改为访问器属性,私下认可值为true

 

留意:IE八是首先个完毕Object.defineProperty()方法的浏览器版本.可是,这几个本子的落到实处存在繁多范围:只可以在DOM对象上运用那几个主意,而且不得不创制访问器属性.由于完成不通透到底,提出不要在IE第88中学使用Object.defineProperty()方法.

[[Enumerable]]:表示是不是通过for-in循环重返属性,暗许值为true

 

2.造访器属性

[[Get]]:在读取属性时调用的函数。暗许值为undefined

 

做客器属性不含有数据值:它们含有①对儿getter和setter函数(可是,那三个函数都不是不可缺少的).在读取访问器属性时,会调用getter函数,那几个函数负责再次回到有效的值;在写入访问器属性时,会调用setter函数并传播新值,那几个函数负责调控哪些处理数据.

[[Set]]:在写入属性时调用的函数。私下认可值为undefined

1

走访器属性有如下四个性状:

 

1

[[Configurable]]:表示能不可能通过delete删除属性从而再度定义属性,能不能修改属性的性状,也许是不是把品质修改为多少属性.对于一贯在指标上定义的习性,那几个特点的暗中认可值为true.

做客器属性不能够一贯定义,必须使用Object.defineProperty()来定义。

 

[[Enumberable]]:表示是或不是通过for-in循环再次回到属性.对于一贯在指标上定义的质量,那个特点的私下认可值为true.

 1     var book = {
 2         _year: 2004,
 3         edition: 1
 4     };
 5 
 6     Object.defineProperty(book,"year",{
 7         get: function(){
 8             return this._year;
 9         },
10         set: function(newValue){
11             if(newValue > 2004){
12                 this._year = newValue;
13                 this.edition += newValue - 2004;
14             } 
15         }
16     });
17 
18     book.year = 2005;
19     console.log(book.edition); //2

 

[[Get]]:在读取属性时调用的函数.私下认可值为undefined.

 

 

[[Set]]:在写入属性时调用的函数.默许值为undefined.

 

 

访问器不能够直接定义,必须选择Object.defineProperty()来定义.

那是选择访问器的大面积方法,即设置陆个性质的值会招致别的质量发生变化,year前边的下划线是一种

 

var book={
        _year:2004,
        edition:1
    };

    Object.defineProperty(book,"year",{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        }
    });

    book.year=2005;
    alert(book.edition);//2

常用的暗记,用于表示只好通过对象方法访问的习性

1

以上代码创建了3个book对象,并给它定义四个暗中同意的性质:_year和edition.

不自然非要同时钦命getter和setter。只钦定getter意味着属性是无法写的,只钦定setter函数的质量
也不能够读

var o = new Object();     //创建一个空对象

_year前边的下划线是壹种常用的记号,用于表示只好通过对象方法访问的属性.而访问器属性year则带有2个getter函数和二个setter函数.getter函数重返_year的值,setter函数通过测算来鲜明科学的版本.这是运用访问器属性的广大方法,即设置3个属性的值会产生其余质量爆发变化.

四个非标准化准的措施:__defineGetter__()和__defineSetter__()

 

不肯定非要同时钦点getter和setter.只钦点getter意味着属性是无法写,尝试写入属性会被忽略.在严酷形式下,尝试写入只钦定了getter函数的属性会抛出错误.类似的,只钦定setter函数的品质也不可能读,不然在非严厉形式下会重返undefined,而在从严情势下会抛出错误.

 1     var book = {
 2         _year: 2004,
 3         edition: 1
 4     };
 5 
 6     book.__defineGetter__("year",function(){
 7             return this._year;
 8         });
 9     book.__defineSetter__("yeat",function(newValue){
10                     if(newValue > 2004){
11                 this._year = newValue;
12                 this.edition += newValue - 2004;
13             } 
14     });
15 
16     book.year = 2006;
17     console.log(book.year);

 

在ECMAScript
伍的这一个点子以前,要创造访问器属性,一般都使用七个非标准化准的情势:_defineGetter_()和_defineSetter_().

 

(3)、Object.create()

在不匡助Object.defineProperty()方法的浏览器中不可能修改[[Configurable]]和[[Enumberable]].

概念多少个本性

它创制3个新目的,当中第1个参数是其一目的的原型,第一个为可选参数,用以对指标的习性进一步描述。

6.一.贰 定义6特天性


它是一个静态函数,而不是提须求有些对象调用的秘技。

出于为对象定义5特性子的只怕相当的大,ECMAScript
5又定义了贰个Object.defineProperties()方法.利用那些主意能够通过讲述符1回定义多个属性.那个措施接收多个对象参数:第3个对象是要充足和退换其质量的对象,第1个对象的属性与第二个对象中要增多或涂改的品质1一对应.

 

如:

var book={};
    Object.defineProperties(book,{
        _year:{
            value:2004
        },

        edition:{
            value:1
        },

        year:{
            get:function(){
                return this._year;
            },
            set:function(){
                if(newValue>2004){
                    this._year=newValue;
                    this.edition+=newValue-2004;
                }
            }
        }    
    });

Object.defineProperties()方法。利用那几个艺术可以透过讲述符3遍定义多少个属性。

 

如上代码在book对象上定义了多少个数据属性(_year和edition)和一个拜访器属性(year).最终的对象与上1节定义的指标一样.唯一的界别是此处的属性都以在同一时间创建的.

 1     var book = {};
 2 
 3     Object.defineProperties(book,{
 4         _year: {
 5             value: 2004
 6         },
 7         edition: {
 8             value: 1
 9         },
10         year: {
11             get: function(){
12                 return this._year;
13             },
14             set: function(newValue){
15                 if(newValue > 2004){
16                     this._year = newValue;
17                     this.edition += newValue - 2004;
18                 }
19             }
20         }
21     });

 

六.一,三 读取属性的性状

 

 

采用ECMAScript
5的Object.getOwnPropertyDescriptor()方法,能够拿走给定属性的叙述符.那一个方法接收多少个参数:属性所在的靶子和要读取其叙述符的性能名称.返回值是多少个对象,倘若是造访器属性,这几个目的的性质有configurable,enumberable,get和set;借使是数码属性,这么些目的的个性有configurable,enumberable,writable和value.

读取属性的性状

 

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;
                }
            }
        }
    });
    var descriptor=Object.getOwnPropertyDescriptor(book,"_year");
    alert(descriptor.value);//2004
    alert(descriptor.configurable);//false
    alert(typeof descriptor.get);//undefined
    var descriptor=Object.getOwnPropertyDescriptor(book,"year");
    alert(descriptor.value);//undefined
    alert(descriptor.enumberable);//undefined
    alert(typeof descriptor.get);//function

2

对此数据属性_year,value等于最初的值,configurable是false,而get等于undefined.对于访问器属性year,value等于undefined,enumerable是undefined,而get是三个针对getter函数的指针.

Object.getOwnPropertyDescriptor()方法,能够得到给定属性的讲述符

2

在JavaScript中,可以针对任何对象–包蕴DOM和BOM对象,使用Object.getOwnPropertyDescriptor()方法.

 

 

 1     Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符
 2 
 3     var book = {};
 4 
 5     Object.defineProperties(book,{
 6         _year: {
 7             value: 2004
 8         },
 9         edition: {
10             value: 1
11         },
12         year: {
13             get: function(){
14                 return this._year;
15             },
16             set: function(newValue){
17                 if(newValue > 2004){
18                     this._year = newValue;
19                     this.edition += newValue - 2004;
20                 }
21             }
22         }
23     });
24 
25     var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
26     console.log(descriptor.value); //2004
27     console.log(descriptor.configurable); //false
28     console.log(typeof descriptor.get); //"underfined"
29 
30     var descriptor = Object.getOwnPropertyDescriptor(book,"year");
31     console.log(descriptor.value); //underfined
32     console.log(descriptor.enumerable); //false
33     console.log(typeof descriptor.get); //"function"

 

 

 

 

 

1

var o = Object.create({ x: 1, y: 2});     //o继承了属性x和y

2

var o2 = Object.create(Object.prototype);    //创建一个空对象

 

 

二、属性的查询和装置

当通过[]来走访对象的属性时,属性名通过字符串来代表。

使用[]运算符访问时,字符串值是动态的,能够在运营时改造。

应用 . 运算符访问时,后接的是标志符,标志符是静态的,写死在程序中。

不等的光景能够行使不相同的演算符来举办走访。

(1)继承

对质量赋值操作时首先要反省原型链,以此推断是不是同意赋值。

假若1个对象承袭自另叁个指标的三个自读属性,那么赋值操作是不一致意的。

比方同意属性赋值操作,它总是在原来对象上创制属性或对已部分属性赋值,而不会去修改原型链。

 

 

 

 

6

6

 

 

 

 

 

1

//这里使用es5 的Object.create()函数来创建对象

2

var o = {r: 1};    //一个用来继承的对象

3

var c = Object.create(o);     //创建一个新对象c,c继承o对象属性r

4

c.x = 1; c.y = 2;     //c定义两个属性

5

c.r = 2;     //c覆盖继承来的属性

6

console.log(o.r);    //1 原型对象没有修改

 

 

(二)、属性访问错误

在转手这个现象下给目的o设置属性p会失败:

  • o中的属性p是只读的:不可能给只读属性重新赋值(defineProperty()方法中有一个比不上,可以对可配置的只读属性重新赋值)。
  • o中的属性p是承继属性,且它是只读的:不能够透过同名自有质量覆盖只读的存在延续属性。
  • o中不设有自有属性p:o未有使用setter方法承袭属性p,并且o的可增加性是false。假如o中不存在p,而且尚未setter方法可供调用,则p一定会增多至o中。但一旦o不是可扩充的,那么在o中不能够定义新属性。

三、删除属性

通过delete运算符能够去除对象的属性。

delete运算符只好删除自有总体性,不能够去除承继属性。(要删减承继属性必须从概念那性子情的原型对象上剔除它,而且那会潜移默化到全部继续自这么些原型的靶子)。

delete不能够去除那一个可配置性为false的品质。(就算能够去除不可扩充对象的可配置属性)

 

 

 

 

6

6

 

 

 

 

 

1

o = {x:1};

2

delete o.x;    //true

3

delete o.x;     //什么也没做(x已经不存在),返回true

4

delete o.toString;     //什么也没做(toString是继承来的) ,返回true

5

delete 1;     //无意义,返回true

6

delete Object.prototype;     //不能删除,属性是不可配置的

 

 

4、检查测试属性

(1)、in运算符

用以检查实验一个对象是还是不是包涵有个别属性,借使目的的自有总体性或几次三番属性中蕴藏那几个性子则赶回true。

如:

 

 

 

 

4

4

 

 

 

 

 

1

var o = { x:1 };

2

"x" in o;     //true "x"是o的属性

3

"y" in o;    //false    "y"不是o的属性

4

"toString" in o;     //true o继承toString属性

 

 

(2)、hasOwnProperty()方法

用来检查测试给定的名字是还是不是是对象的自有品质,对于继续属性它将重回false。

如:

 

 

 

 

澳门葡京,4

4

 

 

 

 

 

1

var o = { x:1 };

2

o.hasOwnProperty("x");    //true o有一个自有属性x

3

o.hasOwnProperty("y");    //false o中不存在属性y

4

o.hasOwnProperty("toString");    //false toString是继承属性

 

 

(3)、propertyIsEnumerable()方法

它用来检查评定是自有属性且那特性格的可枚举性为true时它才再次回到true。

一点内置属性是不可胜道的,经常由javascript代码创造的质量都是可枚举的。如

 

 

 

 

5

5

 

 

 

 

 

1

var o = Object.create({ y: 2});

2

o.x = 1;

3

o.propertyIsEnumerable("x");    // true: o有一个可枚举的自有属性x

4

o.propertyIsEnumerable("y");    //false y是继承来的

5

Object.prototype.propertyIsEnumerable("toString");    //false 不可枚举

 

 

(肆)、决断3个属性是或不是是undefined

使用 “ !== ”,如

 

 

 

 

8

8

 

 

 

 

 

1

var o = { x:1 };

2

o.x !== undefined;     //true o中有属性x

3

o.y !== undefined;     //false o中没有属性y

4

o.toString !== undefined;     //true o继承了toString属性

5

o.z = undefined;

6

o.z !== undefined;     //false 属性存在,但值为undefined

7

delete o.z;    //删除属性

8

"z" in o;    //false,属性不存在

 

 

5、属性getter和setter

在es5中,属性值能够用3个或四个章程代替,这么些多少个措施是getter和setter。由getter和setter定义的天性称做“存取器属性”。

存取器属性不负有可写性。假设属性同时具有getter和setter方法,那么它是3个读/写属性,假如唯有getter方法,那么它是一个只读属性,如若它惟有setter方法,那么它唯有一个只写属性(数据属性中有部分不一致)

getter方法:无参数,再次来到值是性质存取表达式的值。

setter方法:一个参数,设置属性值,

语法:

 

 

 

 

6

6

 

 

 

 

 

1

var o = {

2

    data_prop: value,    //普通的数据属性

3

    //存取器属性

4

    get accessor_prop() { /*函数体 */ },

5

    set accessor_prop() { /*函数体 */ }

6

};

 

 

存取器属性是能够持续的,如

 

 

 

 

21

21

 

 

 

 

 

1

//笛卡尔点坐标对象

2

var p = {

3

x: 1.0,

4

y: 1.0,

5

get r() {

6

return Math.sqrt(this.x * this.x + this.y * this.y);    //this指代这个点的对象,即p

7

},

8

set r(newvalue) {

9

var oldvalue = Math.sqrt(this.x * this.x + this.y * this.y);

10

var ratio = newvalue / oldvalue;

11

this.x *= ratio;

12

this.y *= ratio;

13

},

14

get theta() {

15

return Math.atan2(this.y, this.x);

16

}

17

};

18

var q = Object.create(p);     //创建一个继承getter和setter的新对象

19

q.x = 2, q.y = 1;        //给q添加两个属性

20

console.log(q.r);     //可以使用继承的存取器属性

21

console.log(q.theta);

 

 

6、属性的风味

数据属性包括伍个特征,分别是它的值(value)、可写性(writable)、可枚举性(enumerable)、可配置性(configurable)。存取器属性不享有值本性和可写性,它们的可写性是由setter方法存在与否决定的。因而存取器属性的四性情状是读取(get)、写入(set)、可枚举性和可配置性。

由此调用Object.getOwnPropertyDescriptor()能够获得有些对象特定属性的性质描述符(即意味着五个特征)。

 

 

 

 

16

16

 

 

 

 

 

1

console.log(Object.getOwnPropertyDescriptor({

2

    x: 1

3

}, "x"));     //返回 {value:1, writable:true, enumerable:true, configurable:true}

4

5

var random = {

6

    get octet() {

7

        return Math.floor(Math.random() * 256);

8

    },

9

}

10

//查询定义的random对象的octet属性

11

console.log(Object.getOwnPropertyDescriptor(random, "octet")); 

12

//返回 {get: /*function函数*/, set:undefined, enumerable:true, configurable:true}

13

14

//对于继承属性和不存在的属性,返回undefined

15

console.log(Object.getOwnPropertyDescriptor({}, "x"));    //undefined

16

console.log(Object.getOwnPropertyDescriptor({}, "toString"));    //undefined

 

 

设置属性的特点,恐怕让新建属性具备某种特性,则需要调用Object.definePeoperty(),传入要求修改的指标、要成立或涂改的天性的名号以及品质描述符对象

  

 

 

x

30

 

 

 

 

 

1

var o = {};     //创建一个空对象

2

//添加一个不可枚举的数据属性x,并赋值为1

3

Object.defineProperty(o, "x", {

4

    value: 1,

5

    writable: true,

6

    enumerable: false,

7

    configurable: true

8

});

9

console.log(o.x); //1

10

console.log(Object.keys(o)); //返回[]  keys方法,返回所有可枚举的属性 

11

//对属性x进行修改,让它变为只读

12

Object.defineProperty(o, "x", {

13

    writable: false

14

});

15

o.x = 2; //更改属性值

16

console.log(o.x);    //1 没有被更改,属性是只读

17

18

//属性是可配置的,因此可以通过这种方式对它进行修改

19

Object.defineProperty(o, "x", {

20

    value: 2

21

});

22

console.log(o.x);    // 2

23

//将x从数据属性修改为存取器属性

24

Object.defineProperty(o, "x", {

25

    get: function() {

26

        return 0;

27

    }

28

});

29

console.log(o.x);     // 0

30

console.log(Object.getOwnPropertyDescriptor(o, "x"));     //查看x的特性

 

 

假定须要同时修改或成立多少个属性,并设置属性描述符,则必要选用Object.defineProperties()。参数一为该目的,参数2为多个映射表。如:

 

 

 

 

22

22

 

 

 

 

 

1

//首先创建一个空对象,然后给它添加两个数据属性和一个只读存取器属性。

2

var p = Object.defineProperties({}, {

3

    x: {

4

        value: 1,

5

        writable: true,

6

        enumerable: true,

7

        configurable: true

8

    },

9

    y: {

10

        value: 1,

11

        writable: true,

12

        enumerable: true,

13

        configurable: true

14

    },

15

    r: {

16

        get: function() {

17

            return Math.sqrt(this.x * this.x + this.y * this.y)

18

        },

19

        enumerable: true,

20

        configurable: true

21

    }

22

});

 

 

规则:

  • 一旦指标是不行扩大的,则足以编写制定已某个自有品质,但不能给它丰硕新属性。
  • 如果属性是不足配置的,则无法修改它的可配置性和可枚举性。
  • 假使存取器属性是不可配置的,则不能修改其getter和setter方法,也不可能将它调换为数据属性。
  • 即便数额属性是不行配置的,则无法将它转换为存取器属性。
  • 壹旦数据属性是不足配置的,则不能将它的可写性从false修改为true,但足以从true修改为false。
  • 假如数据属性是不足配置且不可写的,则不可能修改它的值。但是可陈设但不得写属性的值是足以修改的(实际上是先将它标记为可写,然后修改它的值,最终调换为不可写的)。

例子:复制属性的性子

 

 

 

 

21

21

 

 

 

 

 

1

/*

2

    *给Object.prototype添加一个不可枚举的extend()方法

3

    这个方法继承自调用它的对象,将作为参数传入的对象的属性一一复制

4

    除了值之外,也复制属性的所有特性,除非在目标对象中存在同名的属性

5

    参数对象的所有自有对象(包括不可枚举的属性)也会一一复制

6

*/

7

Object.defineProperty(Object.prototype, "extend", {

8

    writable: true,

9

    enumerable: false,     //不可枚举

10

    configurable: true,

11

    value: function(o) {

12

        var names = Object.getOwnPropertyNames(o);     //得到所有的自有属性,包括不可枚举属性

13

        for (var i = 0; i < names.length; i++) {

14

            if (names[i] in this) {        //如果属性已经存在,则跳过

15

                continue;

16

            }

17

            var desc = Object.getOwnPropertyDescriptor(o, names[i]); //获取o中的属性描述符

18

            Object.defineProperty(this, names[i], desc);    //用它给当前对象(this)创建一个属性

19

        }

20

    }

21

});

 

 

7、对象的四个天性

(壹)原型属性

原型属性是在实例对象创造之初就设置好的。

经过Object.getPrototypeOf()方法可以查询有些对象的原型

如:

 

 

 

 

7

7

 

 

 

 

 

1

function People() {}     //空的构造函数

2

People.prototype = {     //设置原型属性

3

    constructor: People,

4

    name: "cart",

5

}

6

var cc = new People();    //实例化构造函数,创建一个新的对象

7

console.log(Object.getPrototypeOf(cc));

 

 

检查测试三个目的是不是是另3个目的的原型,用isPrototypeOf()方法

 

 

 

 

7

7

 

 

 

 

 

1

//定义一个原型对象

2

var p = {

3

    x: 1

4

};

5

var o = Object.create(p);     //使用原型对象创建一个对象

6

console.log(p.isPrototypeOf(o));     // true

7

console.log(Object.prototype.isPrototypeOf(o));     //true o继承p,p继承Object.prototype

 

 

(2)类属性

对象的类属性是一个字符串,用以代表对象的类型消息。

因此toString()方法能够间接的查询到那几个指标的类属性。重回如下格式的字符串:

[
object class ]

所以,要想得到对象的类,可以调用对象的toString()方法,然后提取已再次回到字符串的第九个到倒数第一个职责之间的字符。

 

 

 

 

13

13

 

 

 

 

 

1

// 定义一个获取对象类属性的函数

2

function classof(o) {

3

    if (o === null) {

4

        return "Null";

5

    }

6

    if (o === undefined) {

7

        return "Undefined";

8

    }

9

    return Object.prototype.toString.call(o).slice(8, -1); //间接调用toString方法返回类属性

10

}

11

classof(1);     // NUmber

12

function f() {};     //定于一个自定义构造函数

13

classof(new f());     // Object

 

 

(三)、可增添性

  • 对象的可扩大性用以代表是或不是足以给目的加多新属性。能够经过将对象传入Object.isExtensible(),来推断该对象是不是是可增添的。

  • 1旦想将对象调换为不可扩充的,需求调用Object.preventExtensions(),将待调换的指标作为参数字传送进去。

指标一旦改变为不可扩大,就不可能再将其转移为可扩充的。给二个不得扩张的指标的原型增加属性,这一个不可扩张的靶子一样会持续这么些新属性。

 

 

 

9

9

 

 

 

 

 

1

var o = {

2

    x: 1,

3

    y: {

4

        z: [false, null, ""]

5

    }

6

};

7

console.log(Object.isExtensible(o));    //true

8

Object.preventExtensions(o);    //将对象转换为不可扩展

9

console.log(Object.isExtensible(o));    //false

 

 

  •  
    Object.seal(Object);它除了能够安装对象的不可增加,还足以设置对象的自有总体性都设置为不可配置的,不能够去除和布署。对于它曾经局地可写属性依旧得以设置。
  •    
    Object.isSealed(Object); 检核对象是不是封闭。
  •    
    Object.freeze();更严厉的锁定指标(冻结)。除了将对象设置为不可扩充,属性设置为不可配置,全部的自有质量设置为只读的,(假若指标存款和储蓄器属性有setter方法,存款和储蓄器属性不受影响,依旧得以因此品质赋值给他俩)。
  •    
    Object.isFrozen() 来检验对象是不是冻结。

八、体系化对象

目的体系化(serialization)是指将对象的情景转变为字符串,也足以将字符串还原为对象。

采纳函数JSON.stringify()和JSON.parse()用来体系化和还原javascript对象。

 

 

 

 

11

 

 

 

 

 

1

// 定义一个测试对象

2

var o = {

3

    x: 1,

4

    y: {

5

        z: [false, null, ""]

6

    }

7

};

8

var s = JSON.stringify(o);

9

var p = JSON.parse(s);

10

console.log(s);    //解析为json格式字符串 {"x":1,"y":{"z":[false,null,""]}}

11

console.log(p);    //将字符串转换为javascript对象

 

 

函数、RegExp、Error对象和undefined值不能够种类化和恢复。JSON.stringify()只好系列化对象可枚举的自有总体性。

 

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website