原型与继承学习笔记2

时间:2022-08-24 23:17:40

上节我们讨论了对象的定义和对象的创建,知道了函数也是对象,知道了对象都是由函数创建的,知道了对象的原型和函数的原型属性的关系。这节说一下关于对象属性的操作,下节就可以切入正题了。

    属性删除

 1 var person = {age : 28, title : 'fe'};
 2 delete person.age; // true
 3 delete person['title']; // true
 4 person.age; // undefined
 5 delete person.age; // true
 6 
 7 delete Object.prototype; // false,
 8 
 9 var descriptor = Object.getOwnPropertyDescriptor(Object, 'prototype');
10 console.log(descriptor)     //Object {value: Object, writable: false, enumerable: false, configurable: false}

 

delete操作符删除一个属性值后会返回true,第5行也返回true是因为person.age已经是个undefined,所以仍然会返回一个true,第7行删除Object的prototype属性返回了一个false,我们可以通过第9行Object.getOwnPropertyDescriptor()方法查看一下Object.prototype的特性,configurable属性值为false(不可配置),因此返回false。

    属性检测

1 var cat = new Object();
2 cat.legs=4;
3 'legs' in cat;      //true
4 'toString' in cat;      //false
5 cat.propertyIsEnumerable('legs'); // true
6 cat.propertyIsEnumerable('toString'); // false

 

 使用propertyIsEnumerable()可以判断一个属性是不是可枚举的,如果想设置一个属性的特性是不是可枚举的怎么办呢,看下边:

1 Object.defineProperty(cat, 'price', {enumerable : true, value : 1000});
2 cat.propertyIsEnumerable('price'); // true
3 cat.hasOwnProperty('price'); // true

 

使用Object.defineProperty()方法可以设置属性的特性值,如上我们可以把可枚举的特性设置为true或false。

    属性枚举

in关键字可以判断属性是否存在,for in语句则不能枚举enumerable 值为false的属性,如:

1 var o={a:'1',b:'2'}
2 Object.defineProperty(o,'c',{
3     Enumberable:false
4 });
5 console.log('c' in o)   //true
6 var key;
7 for(key in o){
8     console.log(key)    //a,b
9 }

    get/set方法

get/set方法是另一种进行属性操作的方式,如:

 1 var man = {
 2     name : 'James',
 3     get age() {
 4         return new Date().getFullYear() - 1988;
 5     },
 6     set age(val) {
 7         console.log('Age can\'t be set to ' + val);
 8     }
 9 }
10 console.log(man.age); // 27
11 man.age = 100; // Age can't be set to 100
12 console.log(man.age); // 27

 

取一个属性值age时会触发get方法,给age赋值时触发set方法,赋值成不成功取决于set方法内部是否会对属性进行修改。

    属性标签

1 Object.getOwnPropertyDescriptor({pro : true}, 'pro');
2 // Object {value: true, writable: true, enumerable: true, configurable: true}
3 Object.getOwnPropertyDescriptor({pro : true}, 'a'); // undefined

 

 前边提到过这个方法,可以返回一个属性特性描述的对象,分别有4个属性,value表示属性值,writable表示属性值是否可写,enumberable表示属性值是否可被枚举,configurable表示属性是否可被用其他方式进行操作(如delete操作符)。

 1 Object.defineProperties(person, {
 2     title : {value : 'fe', enumerable : true},
 3     corp : {value : 'BABA', enumerable : true},
 4     salary : {value : 50000, enumerable : true, writable : true},
 5     luck : {
 6         get : function() {
 7         return Math.random() > 0.5 ? 'good' : 'bad';
 8         }
 9     },
10     promote : {
11         set : function (level) {
12             this.salary *= 1 + level * 0.1;
13         }
14     }
15 });
16 
17 Object.getOwnPropertyDescriptor(person, 'salary');
18 // Object {value: 50000, writable: true, enumerable: true, configurable: false}
19 Object.getOwnPropertyDescriptor(person, 'corp');
20 // Object {value: "BABA", writable: false, enumerable: true, configurable: false}
21 person.salary; // 50000
22 person.promote = 2;
23 person.salary; // 60000

 

使用Object.defineProperties()方法可以定义多个属性的值,而且get,set方法可以不针对同一个属性进行操作,这个例子可以系统包含整个知识点。所有的属性特性值不输入均默认为false。

下图提供了configurable和writable不同情况下的操作影响:

原型与继承学习笔记2

可以看出这两个属性值均为true时我们基本可以做任何操作,属性都为false时我们都做不了,其他情况就不再赘述了。

    对象标签

对象标签有三个:__proto__,__class__,__extensible__,__proto__下节讨论。

__class__属性无法直接访问,我们只能借助于Object.toString方法来简介访问到,如下:

 1 var toString = Object.prototype.toString;
 2 function getType(o){return toString.call(o).slice(8,-1);};
 3 
 4 toString.call(null); // "[object Null]"
 5 getType(null); // "Null"
 6 getType(undefined); // "Undefined"
 7 getType(1); // "Number"
 8 getType(new Number(1)); // "Number"
 9 typeof new Number(1); // "object"
10 getType(true); // "Boolean"
11 getType(new Boolean(true)); // "Boolean"

 

__extensible__标签表示对象是否可扩展,即该对象是否可以继续添加属性,看下边代码:

 1 var obj = {x : 1, y : 2};
 2 Object.isExtensible(obj); // true
 3 Object.preventExtensions(obj);
 4 Object.isExtensible(obj); // false
 5 obj.z = 1;
 6 obj.z; // undefined, add new property failed
 7 Object.getOwnPropertyDescriptor(obj, 'x');
 8 // Object {value: 1, writable: true, enumerable: true, configurable: true}
 9 
10 Object.seal(obj);
11 Object.getOwnPropertyDescriptor(obj, 'x');
12 // Object {value: 1, writable: true, enumerable: true, configurable: false}
13 Object.isSealed(obj); // true
14 
15 Object.freeze(obj);
16 Object.getOwnPropertyDescriptor(obj, 'x');
17 // Object {value: 1, writable: false, enumerable: true, configurable: false}
18 Object.isFrozen(obj); // true
19 
20 // [caution] not affects prototype chain!!!

 

第2行代码使用Object.isExtensible()方法,我们可以检测是否可以进行对象属性扩展,然后Object.preventExtensions()方法,我们可以设置对象不能进行扩展,但该对象属性标签的原始值仍然保持不变,如第7行;

使用seal()方法会将该对象的所有属性标签的configurable值设置为false,而freeze()方法会将该对象的所有属性标签的configurable和writable值均设置为false。

 

下节开始讨论__proto__原型链和继承相关内容。

原型与继承学习笔记3http://www.cnblogs.com/wangxiaosan/p/5541795.html