1.原型-原型链
(1)原型
prototype属性:
所有的构造函数new出来的实例化对象,都会有一个prototype属性,这个prototype属性指向的构造函数的原型对象(内存地址)调用属性和方法的时候,先去构造中查找,如果构造中没有,会沿着prototype属性的内存地址,再原型对象中查找有没有对应方法
原型对象的意义:实例话对象在访问属性和方法时,会先访问自身的属性和方法,如果自身不存在对应的属性和方法,则会自动通过proto属性找到原型对象,如果原型对象上存在,则也能正确调用
原型对象是为了实现继承
function Person(name,age){
this.name=name;
this.age=age;
this.say=function(){
alert('我偷偷告诉你:'+this.name+"今年"+this.age+'岁了');
}
}
var p1 = new Person('jack',20); // 作为构造函数调用
p1.say();
var p2 = new Person('Rose',26); // 作为构造函数调用
p1.say();
// 原型对象在初始化时,有两个属性:
// 1. constructor: 构造器,指向构造函数本身 (开发中基本不用,主要是理解)
console.log(Student.prototype.constructor);
// 2. __proto__:指向它上一级构造函数的原型对象
console.log(Student.prototype.__proto__);
(2)原型链
原型对象也是对象,所以它也有原型,当我们使用或访问一个对象的属性或方法时:
- 它会先在对象自身中寻找,如果有则直接使用;
- 如果没有则会去原型对象中寻找,如果找到则直接使用;
- 如果没有则去原型的原型中寻找,直到找到Object对象的原型。
- Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回 null
原型对象默认不是空的,默认情况下里面有两个方法,分别是constructor[构造器]和** proto **
**原型链:**由prototype属性,串联起来的原型对象,就称为是原型链
**原型链的意义:**实例化对象中访问属性和方法的时候,先访问自身的属性和方法,本身不存在,则会通过prototype属性,再整个原型链上查找,如果整个都查找不到就会报错
function Student(name,age,address){
this.name = name;
this.age = age;
this.address = address;
this.say = function(){
console.log('我是',this.name,'我来自'+this.address);
}
}
Object.prototype.move = function(){ // 给Object添加原型方法
console.log('会移动');
}
var one = new Student('Jack',19,'郑州');
one.move(); // ok!从one中调用move方法
var d = new Date();
d.move() // 可以调用么?可以!
var arr = [1,2,3];
arr.charAt(); // 报错
arr.move(); // 可以!
总结:new一个实例话对象经历的四个阶段:
- 创建一个空的实例化对象
- 让构造函数中的this指向空的实例化对象
- 执行(调用)构造函数,从而创建实例化对象自身的属性和方法
- 返回实例化对象
总结:
1. 原型对象:所有的构造函数在初始化时,都会自动生成一个特殊的实例话对象,构造函数的prototype属性指向该对象,该对象称为原型对象,或prototype对象
2. __proto__对象:所有构造函数new出来的实例话对象,都有一个__proto__属性,该属性指向构造函数的原型对象,原型对象也有自己的__proto__属性,指向上一级构造函数的原型对象,__proto__会一直找到Object的原型对象,object原型对象的__proto__指向null
3. 原型链:由一系列__proto__属性,串联起来的原型对象,称为原型链
4. 原型链的意义:实例化对象在访问属性和方法时,会先访问自身的属性和方法,如果自身不存在对应的属性和方法,则会自动通过__proto__属性在整个原型链上查找,只要找到对应的属性和方法,就能正确执行,如果原型链上没找到,则报错