原型形式
定义组织函数,在组织函数的原型对象中定义对象的属性和要领,并经由过程组织函数建立对象。
1.建立对象
function Person(){};
Person.prototype.name = "Mike";
Person.prototype.age = 20;
Person.prototype.job = "student";
Person.prototype.showName = function(){
console.log("name = " + this.name);
};
var p1 = new Person();
var p2 = new Person();
console.log(p1);
console.log(p2);
2.探讨原型对象
运用原型对象的优点是可以让一切对象实例同享它包括的属性和要领,即p1和p2接见的都是统一组属性和统一个showName()函数。
但转变原型对象上的属性时,一切实例对象上对应的属性也同时转变。
Person.prototype.job = "teacher";
Person.prototype.showJob = function(){
console.log("job = " + this.job);
};
p1.showJob();
p2.showJob();
console.log("p1.showJob === p2.showJob:");
console.log(p1.showJob === p2.showJob);
console.log("-----分割线-----");
当代码读取对象的某个属性时,都邑实行最少一次搜刮。搜刮起首从实例对象最先,若在实例对象中搜刮到了婚配的属性,则返回该属性的值;若无,在搜刮该实例对象的__proto__指针指向的原型对象,若在原型对象中搜刮到了婚配的属性,则返回该属性的值;若无,则输出undefined
。
p1.country = "China";
console.log("p1.country=");
console.log(p1.country); //China
console.log("p2.country=");
console.log(p2.country); //Undefined
console.log("-----分割线-----");
Person.prototype.country = "USA";
console.log("p1.country=");
console.log(p1.country); //搜刮先婚配到了实例对象p1上的country属性,返回值为"China"
console.log("p2.country=");
console.log(p2.country); //第一次搜刮婚配不到实例对象p2上的country属性,实行第二次搜刮,婚配到原型对象上的country属性,返回值为"USA"
console.log("-----分割线-----");
所以,我们没法经由过程修正实例对象来重写原型中的属性。
当为实例对象增加一个属性时,这个属性就会屏障原型对象中保留的同名属性,即使我们将其设置为null,也只会在实例中设置这个属性,而不会恢复其指向原型的衔接。不过,运用delete操作符可以完整删除实例对象的属性。
p1.country = null;
console.log("p1.country=");
console.log(p1.country); //null
console.log("p2.country=");
console.log(p2.country); //USA
console.log("-----分割线-----");
// delete操作符可以完整删除实例属性,从而让我们可以从新接见原型中的属性
delete p1.country;
console.log("p1.country=");
console.log(p1.country);
console.log("p2.country=");
console.log(p2.country);
console.log("-----分割线-----");
我们可以经由过程hasOwnProperty()
要领检测一个属性是存在于实例中,照样原型中。这个要领只在给定属性存在于实例对象中,才会返回true。
别的,in
操作符会在经由过程对象可以接见给定属性时返回true,不管这个属性是存在于实例中照样原型中。
// 先给p1实例对象定义country属性
p1.country = "China";
// hasOwnProperty()要领可以检测一个属性是存在于实例中,照样存在于原型中。
// 只在给定属性存在于对象实例中时,才会返回true。
// 此要领继续自Object。
console.log("p1.hasOwnProperty(country):");
console.log(p1.hasOwnProperty("country")); //true,country属性存在于实例对象p1中
console.log("p2.hasOwnProperty(country):");
console.log(p2.hasOwnProperty("country")); //false,country属性不存在于实例对象p2中
console.log("-----分割线-----");
// in操作符会在经由过程对象可以接见给定属性时返回true,不管该属性是存在于实例中照样原型中。
console.log("country in p1:");
console.log("country" in p1); //true
console.log("country in p2:");
console.log("country" in p2); //true
console.log("-----分割线-----");
3.视察Person组织函数涉及到的原型链**
console.log("Person.prototype=");
console.log(Person.prototype);
console.log("Person.prototype === Function.prototype;");
console.log(Person.prototype === Function.prototype); //false
console.log("-----分割线-----");
console.log("Person.prototype.constructor === Person:"); //true
console.log(Person.prototype.constructor === Person); //true
console.log("-----分割线-----");
console.log("Person.prototype.__proto__ === Object.prototype:"); //true
console.log(Person.prototype.__proto__ === Object.prototype); //true
console.log("-----分割线-----");
console.log("Person.__proto__=");
console.log(Person.__proto__);
console.log("Person.__proto__ === Function.prototype:");
console.log(Person.__proto__ === Function.prototype); //true
console.log("-----分割线-----");
4.视察p1实例对象涉及到的原型链
console.log("p1.prototype=");
console.log(p1.prototype);
console.log("-----分割线-----");
console.log("p1.__proto__=");
console.log(p1.__proto__);
console.log("p1.__proto__ === Person:");
console.log(p1.__proto__ === Person); //false
console.log("p1.__proto__ === Person.prototype:");
console.log(p1.__proto__ === Person.prototype); //true
console.log("-----分割线-----");
console.log("p1.__proto__.constructor === Person:");
console.log(p1.__proto__.constructor === Person);
console.log("-----分割线-----");
console.log("p1.__proto__.__proto__=");
console.log(p1.__proto__.__proto__);
console.log("p1.__proto__.__proto__ === Object.prototype:");
console.log(p1.__proto__.__proto__ === Object.prototype); //true
console.log("-----分割线-----");
5.视察下p1.showName属性援用的函数
console.log("p1.showName.prototype=");
console.log(p1.showName.prototype);
console.log("p1.showName.prototype === Function.prototype:");
console.log(p1.showName.prototype === Function.prototype); //false
console.log("-----分割线-----");
console.log("p1.showName.prototype.constructor=");
console.log(p1.showName.prototype.constructor);
console.log("-----分割线-----");
console.log("p1.showName.prototype.__proto__=");
console.log(p1.showName.prototype.__proto__);
console.log("p1.showName.prototype.__proto__ === Object.prototype:");
console.log(p1.showName.prototype.__proto__ === Object.prototype); //true
console.log("-----分割线-----");
console.log("p1.showName.__proto__=");
console.log(p1.showName.__proto__);
console.log("p1.showName.__proto__ === Function.prototype:");
console.log(p1.showName.__proto__ === Function.prototype); //true
console.log("-----分割线-----");