在JavaScript中,咱们每建立一个函数,都会有一个prototype(原型)属性:这个属性是一个指针,指向一个对象,对象的用途是包含能够由特定类型的全部实例共享的属性和方法浏览器
prototype 就是经过调用构造函数而建立的那个对象实例的原型对象。使用原型可让全部对象实例共享它所包含的属性和方法bash
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
person1.sayHello(); //"lilei:hello"
var person2 = new Person();
person2.sayHello(); //"lilei:hello"
console.log(person1.sayHello == person2.sayHello); //true
复制代码
全部原型对象都会自动得到一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。如图3-1:Person.prototype.constructor 指向 Person。函数
Person.prototype.constructor === Person // true
复制代码
实例化的对象内部有一个看不见的__proto__指针,指向原型对象,__proto__只在浏览器内部使用,__对脚本则是彻底不可见的。虽然在全部实现中都没法访问到__proto__,但能够经过 isPrototypeOf()方法来肯定对象之 间是否存在这种关系:this
console.log(Person.prototype.isPrototypeOf(person1)); //true
console.log(Person.prototype.isPrototypeOf(person2)); //true
复制代码
全部对象的__proto__都指向其构造函数的prototypespa
person1.__proto__ === Person.prototype //true
复制代码
Person.__proto__ === Function.prototype // true
Number.__proto__ === Function.prototype // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === Function.prototype // true
RegExp.__proto__ === Function.prototype // true
Error.__proto__ === Function.prototype // true
Date.__proto__ === Function.prototype // true
复制代码
因此全部构造函数都继承了Function.prototype的属性及方法prototype
console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype) // object
console.log(typeof Number.prototype) // object
console.log(typeof Boolean.prototype) // object
console.log(typeof String.prototype) // object
console.log(typeof Array.prototype) // object
console.log(typeof RegExp.prototype) // object
console.log(typeof Error.prototype) // object
console.log(typeof Date.prototype) // object
console.log(typeof Object.prototype) // object
复制代码
Function.prototype.__proto__ === Object.prototype // true
Person.prototype.__proto__ === Object.prototype // true
Number.prototype.__proto__ === Object.prototype // true
Boolean.prototype.__proto__ === Object.prototype // true
String.prototype.__proto__ === Object.prototype // true
Array.prototype.__proto__ === Object.prototype // true
Function.prototype.__proto__ === Object.prototype // true
RegExp.prototype.__proto__ === Object.prototype // true
Error.prototype.__proto__ === Object.prototype // true
Date.prototype.__proto__ === Object.prototype // true
复制代码
Object.prototype的__proto__?设计
Object.prototype.__proto__ === null // true
复制代码
person1.constructor === Person.prototype.constructor //true
person1.constructor === Person //true
person1.name === Person.prototype.name //true
person1.age === Person.prototype.age //true
person1.sayHello === Person.prototype.sayHello //true
复制代码
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg" ——来自实例
console.log(person2.name); // "lilei" ——来自原型
复制代码
访问person1.name时会在这个实例上搜索一个名为 name的属性。这个属性若是存在,就返回,不存在 就到原型上去找。当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性;添加这 个属性只会阻止咱们访问原型中的那个属性,但不会修改那个属性指针
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg" ——来自实例
console.log(person2.name); // "lilei" ——来自原型
delete person1.name;
console.log(person1.name); // "lilei" ——来自原型
复制代码
person1.name = "Greg";
person1.hasOwnProperty("name") //true
person2.hasOwnProperty("name") //false
复制代码
当 person1 重写name 属性后返回 true,由于这时候 name 是一个实例属性,而非原型属性code
person1.name = "Greg";
person1.hasOwnProperty("name") //true
person2.hasOwnProperty("name") //false
console.log("name" in person1) //true
console.log("name" in person2) //true
复制代码
function Person(){}
Person.prototype = {
constructor: Person,
name : "lilei",
age : 26,
friends : ["Jim", "Tom"]
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("hanmeimei");
console.log(person1.friends); //"Jim,Tom,hanmeimei"
console.log(person2.friends); //"Jim,Tom,hanmeimei"
console.log(person1.friends === person2.friends); //true
复制代码
每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型 对象的内部指针。若是咱们让原型对象等于另外一个类型的实例,会发生什么?因此下一节《继承》cdn
《JavaScript 高级程序设计》中文译本 第三版