prototype

在prototype上有一个叫做constructor的属性,Person.prototype.constructor指向Person,当new Person的时候,每个实例会有一个[[prototype]]指向该对象构造函数的prototype,在chrome里面就是__proto__属性可以查看,但这不是标准的方法(ecmascript 6 把它标准化),因此实例和构造函数的prototype是有可接入的直接联系,但是实例和构造函数之间没有建立联系
 
 
判断一个对象的[[Prototype]]是否指向某个prototype对象:
alert(Person.prototype.isPrototypeOf(person1));                             //true
alert(Person.prototype.isPrototypeOf(person2));                            //true
 
使用Object.getPrototypeOf( Internet Explorer 9+,Firefox 3.5+, Safari 5+, Opera 12+, and Chrome)来取得[[Prototype]]上的值:
alert(Object.getPrototypeOf(person1) == Person.prototype);                   //true
alert(Object.getPrototypeOf(person1).name);                                               //”Nicholas”
 
变量查找就是沿着实例和构造函数原型间的关系来的,首先在实例本身上找有没有需要的属性方法,没有的话就找构造函数原型上有没有。实例上也能访问到constructor属性值
 
 
当在实例上添加一个属性方法时,只是添加在当前实例上,不会覆盖构造函数原型上的。当你删除时,也是删除这个实例上的:
 
当实例上有找到属性或方法,就不会再去读取构造函数原型上的了,只有你把这个属性方法delete了,才会读取构造函数原型上的,因此有一个方法hasOwnProperty用来判断一个属性到底在哪,可以用来检测一个属性是否只存在于他的构造函数prototype上(用in来检测只要在实例或者prototype上存在该属性都会返回true):
function hasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
}
 
使用for-in循环的时候,也会把返回实例上和构造函数原型上的属性。
 
创建真正的空对象:
使用  var  obj  =  Object.create(null);   
将会创建真正意义上的空对象,原型链上也是空的
而使用   var  obj =   {};  
这样obj 的原型将会指向一个位于 Object.prototype  上的对象,继承相应方法
(The most important thing about the expanded form is that object literals always set the newly created object’s prototype to an object located at Object.prototype.)
 
在这个构造函数里,name是一个存取器(assessor)属性,用来保存真正的名字,在strict模式里面,如果使用构造函数忘记new会出错,this不会指向全局window对象,this会保持为 undefined:
function Person(name) {
    Object.defineProperty(this, "name", {
        get: function() {
            return name; 
        },
        set: function(newName) {
            name = newName;
       },
       enumerable: true,
       configurable: true
     });
     this.sayName = function() {
         console.log(this.name);
     };
}
 
直接在原型上扩展的方法在所有实例都是可见的(继承了),Person.prototype.sayHi,但是如果重写整个prototype对象,就是新建了一个Object的实例,再把prototype指向新的实例对象,就会隔断构造函数和旧的prototype:
function Person(){ }
var friend = new Person();
Person.prototype = { 
    constructor: Person, 
    name : “Nicholas”, age : 29,
    job : “Software Engineer”, 
    sayName : function () {
        alert(this.name); }
};
friend.sayName();             //error   friend实例指向的是旧的Person.prototype,而不是新的,新的实例才是指向新的
 
同时要注意实例的constructor会消失,因为constructor属性是在prototype对象上的:
Person.prototype = {
    constructor : Person,                 //  防止指向构造函数的引用失效,  person1.constructor === Person 才会返回true,不过这样添加的是可遍历的,默认是不可遍历的
    sayName : function () {
        console.log( this.name);
    },
    toString : function () {
        return "[Person " + this .name + "]" ;
    }
};
 
 
当使用Object.seal() 或者 Object.freeze()的时候,就不能在实例上新增属性方法了,但是可以通过原型对象添加
 
 
Object.keys()  可以返回可遍历的实例属性:
function Person(){}
 
Person.prototype.name = “Nicholas”;
Person.prototype.age = 29;
Person.prototype.job = “Software Engineer”;
Person.prototype.sayName = function(){
 alert(this.name);
};
var keys = Object.keys(Person.prototype);
alert(keys);                                                                     //”name,age,job,sayName”
var p1 = new Person();
p1.name = “Rob”;
p1.age = 31;
var p1keys = Object.keys(p1);
alert(p1keys);                                                            //”name,age”
 
 Object.getOwnPropertyNames()可以返回所有实例属性,不管是可遍历还是不可遍历:
var keys = Object.getOwnPropertyNames(Person.prototype);                                      //”constructor,name,age,job,sayName”                                                                               
原文地址:https://www.cnblogs.com/chuangweili/p/5165768.html