js 对象中属性的来源

通过对对象的创建,继承的理解,我们可以发现,在平时使用时,prototype和实例中的属性都可以直接通过this.para来调用。而且优先使用实例中的属性,然后在根据原型链一步步的向上寻找属性的位置,直到找到为止。在平时,这些机制对于我们使用对象有很大帮助,但是有时候会产生实例属性覆盖原型属性,使我们调用不到正确的值。这时候我们就首先要判断我们现在能得到的属性来自于哪个位置。

首先是in操作符,in操作符可以判断某个属性在对象中能否被访问,不管是在实例中还是原型中。看以下这个例子:

 1 function Myobj(){
 2     this.name='Tom';
 3     this.age='20';
 4 }
 5 Myobj.prototype.getName = function(){
 6     console.log(this.name);
 7 }
 8 var obj = new Myobj();
 9 console.log('name' in obj);
10 console.log('getName' in obj);

最后两个console.log返回的都是true,这样就有了可以确定某个属性是否在这个对象中了。

接下来就是hasOwnProperty了,它可以判断某个属性是来自实例中还是原型中。对于在实例中的属性会返回true,而在原型中的属性会返回false,看下面这个例子:

 1 function Myobj(){
 2 }
 3 Myobj.prototype.name = 'Peter';
 4 Myobj.prototype.getName = function(){
 5     console.log(this.name);
 6 }
 7 var obj = new Myobj();
 8 console.log(obj.hasOwnProperty('name'));        //false
 9 obj.name = 'Tom';
10 console.log(obj.hasOwnProperty('name'));        //true
11 delete obj.name;
12 console.log(obj.hasOwnProperty('name'));        //false

通过hasOwnProperty方法的使用,我们可以清楚的知道我们访问的到底是实例属性,还是来自原型或原型链中的属性。在调用obj.hasOwnProperty('name')时,只有重写name属性,才能使name成为一个实例属性,那么才会返回true。delete删除了这个name实例属性后,hasOwnProperty又会返回false了。

根据以上的这些函数的特性,我们可以编写一个函数来检测属性是否来自于原型:

1 function isParaFromProto(obj,para){
2     if(para in obj){
3         return (!obj.hasOwnProperty(para))?true:false;
4     }else{
5         throw new Error('para not in obj');
6     }
7 }

函数的使用如下:

 1 function Myobj(){
 2 }
 3 Myobj.prototype.name = 'Peter';
 4 Myobj.prototype.getName = function(){
 5     console.log(this.name);
 6 }
 7 var obj = new Myobj();
 8 console.log(isParaFromProto(obj,'name'));        //true
 9 obj.name = 'Tom';
10 console.log(isParaFromProto(obj,'name'));        //false
11 delete obj.name;
12 console.log(isParaFromProto(obj,'name'));        //true

关于in操作符

in操作符主要有两个用处,一个是以上介绍过的,另一个是用在for语句中。但是两处地方在一些设置更改以后还是有不同的地方。Object中定义有defineProperty方法,它可以设置对象中属性的特性(不能设置原型中的属性),通过将Enumerable属性设置为false,那么for in循环就无法遍历到这个属性了,就想object中原生的__proto__属性。但是这时用in操作符判断属性是否在对象中时,还是可以返回true的。

 1 function Myobj(){
 2     this.name = 'Tom';
 3 }
 4 var obj = new Myobj(),arr = [];
 5 for(var i in obj){
 6     arr.push(i);
 7 }
 8 console.log(arr);                  //['name']
 9 console.log('name' in obj);        //true
10 arr=[];
11 Object.defineProperty(obj,'name',{enumerable:false});
12 for(var i in obj){
13     arr.push(i);
14 }
15 console.log(arr);                  //[]
16 console.log('name' in obj);        //true
原文地址:https://www.cnblogs.com/cyITtech/p/3564189.html