一、原型
一个可以被复制(克隆)的一个类,通过复制原型可以创建一个一模一样的新对象,也可以说原型就是一个模板,在设计语言中更准确的说是一个对象模板
1、原型是定义了一些公用的属性和方法,利用原型创建出来的新对象实例会共享原型的所有属性和方法
function Cat(name, age) {
this.name = name
this.age = age
// 给实例添加eat方法,将来每一个对象都有这个eat方法,造成空间浪费
// this.eat = function () {
// console.log('猫吃老鼠')
// }
}
// 给Cat原型添加公共的属性或方法,这样所有new出来的实例都可以访问
Cat.prototype.eat = function () {
console.log('猫吃老鼠')
}
Cat.prototype.nation = 'china'
2、原型的属性和方法还是会被原型实例所共享的
// 创建原型
var Person = function(name){
this.name = name;
};
// 原型的方法
Person.prototype.sayHello = function(){
console.log(this.name+",hello");
};
// 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
var person1 = new Person("zhangsan");
var person2 = new Person("lisi");
// zhangsan,hello
person1.sayHello();
// lisi,hello
person2.sayHello();
3、通过原型创建的新对象实例是相互独立的,为一个实例对象添加新属性或方法,其他实例对象无法调用该属性、方法
// 为新对象实例添加方法
// 通过原型创建的新对象实例是相互独立的
person1.getName = function(){
console.log(this.name);
}
// zhangsan
person1.getName();
// Uncaught TypeError: person2.getName is not a function
person2.getName();
4、函数的原型 prototype:JS为每个构造函数提供一个属性prototype(原型),它的值是一个对象,prototype也叫原型对象
5、函数的原型对象 __proto__:所有对象都有__proto__属性, 当用构造函数实例化(new)一个对象时,会将新对象的__proto__属性指向 构造函数的prototype
6、构造函数、原型对象、实例函数之间的关系
// 创建一构造函数
function Student(id,name,age){
this.id=id
this.name=name
this.age=age
}
// 原型对象创建一个方法
Student.prototype.exercise=function(){
console.log('打篮球')
}
Student.prototype.name='ccc'
const stu1=new Student(01,'abc',20)
console.log(stu1)
Student.prototype.exercise() // 打篮球
console.log(stu1.name) // abc 就近原则
通过该关系图我们可以得出以下结论:
Student.prototype.constructor===Student
stu1.__proto__===Srudent.prototype
stu1.constructor===Student
7、原型的使用方式
通过给Calculator对象的prototype属性赋值对象字面量来设定Calculator对象的原型
在赋值原型prototype的时候使用function立即执行的表达式来赋值,可以封装私有的function,通过return的形式暴露出简单的使用名称,以达到public/private的效果
二、原型链
当调用某个函数的方法时,这个函数未定义这个方法,此时不会返回undefined,而是继续往原型链后面的原型去查找,只有查找不到,才返回undefined。
1、 原理: 每个对象都有隐式原型(__proto__)和显式原型(prototype),对象的__proto__指向它原型对象上的prototype。原型链最终指向的是Object.prototype,他的__proto__为null
2、原型链结构图示例图:
arr.__proto__=== Array.prototype
arr.__proto__.__proto__===Object.prototype
Array.prototype.__proto__===Object.prototype
Function.__proto__.__proto===[].__proto__.__proto__
...
3、prototype 和 proto 区别是什么?
1)prototype是构造函数的属性
2) __proto__是每个实例都有的属性,可以访问 [[prototype]] 属性
3)实例的__proto__与其构造函数的prototype指向的是同一个对象