JavaScript的原型对象(prototype)——函数的&对象的

1、每个函数都有一个【prototype】属性,这个属性其实是个指针,指向的是该函数的原型对象,因此,我们可以通过这个属性设置和访问该函数的原型对象,如:

function F() {
     
    this.name = "Xiao Ming";
}
F.prototype = {
    sayName : function() {
     
        return this.name;
    }
};
console.log(F.prototype);   //{sayName: ƒ}

2、每个对象都有一个【__proto__】属性,而这个属性其实是一个浏览器(Firefox、Safari、Chrome、IE11等浏览器有写入)的内置属性,并非正式的开放API,这个属性也是一个指针(即是对指针【[[Prototype]]】的一种访问实现),指向该对象的原型对象(原型对象的默认属性和方法是从【Object】继承而来的),所以我们也可以通过这个属性来设置和访问该对象的原型对象,如:

var obj = {
    name : "Xiao Ming"
};
obj.__proto__ = {
    sayName : function() {
     
        return this.name;
    }
};
console.log(obj);   //{name: "Xiao Ming"}
console.log(obj.sayName());     //Xiao Ming
console.log(obj.__proto__);     //{sayName: ƒ}

由于这个属性并非可用的正式API,故,在ES5中新增了【Object.setPrototypeOf()】方法来实现为指定对象设置原型对象,和【Object.getPrototypeOf()】方法来实现获取指定对象的原型对象。在上面代码的基础上测试如下:

Object.setPrototypeOf(obj, {
    stop : function() {
     
        return;
    }
});
console.log(Object.getPrototypeOf(obj));    //{stop: ƒ}
console.log(obj.__proto__);     //{stop: ƒ}

结合1&2补充说明:函数默认没有【__proto__】属性,对象默认没有【prototype】属性。

3、说说构造函数与实例在原型对象上的关系,如下:

function F() {
     
    this.name = "Xiao Ming";
}
F.prototype = {
    sayName : function() {
     
        return this.name;
    }
};
var f = new F();

现有构造函数【F】和其实例【f】。我们知道,实例的内部存在一个指针,指向所属构造函数的原型对象,因此,构造函数的所有实例便可以共享构造函数原型对象上的属性和方法。而实例又是一个对象:

console.log(typeof f);  //object

根据上面 2 中所述,每个对象都有自己的内部指针【__proto__】,指向该对象的原型对象,通过:

console.log(f.__proto__);   //{sayName: ƒ}
console.log(Object.getPrototypeOf(f));  //{sayName: ƒ}

我们可以看到【f】的【__proto__】的内容就是【F】的原型对象的内容,即实例【f】这时的原型对象就是【F】的原型对象了(这一句表达的好像有点不准确,大概意思就是这样的)。当然,我们可以通过修改【__proto__】的指向来改变实例的原型对象的内容,如:

f.__proto__ = {
    age : 0
};
//或者使用:
//Object.setPrototypeOf(f, {
     
//  age : 0
//});
console.log(Object.getPrototypeOf(f));  //{age: 0}
console.log(F.prototype);    //{sayName: ƒ}

并且不会影响到【F】的原型对象,因为这是直接改变了【f】的指针指向。但如果通过【__proto__】来修改原型对象的属性的话,就会影响到【F】的原型对象了,如:

f.__proto__.sayName = "修改后";
console.log(F.prototype);    //{sayName: "修改后"}

当然,这是由于原型对象的值是引用类型导致的,所用实例要使用【__proto__】时需谨慎。

你可能感兴趣的:(前端,-,JS,prototype,javascript,函数,对象,原型对象)