几个定义
function Person(){}
var person = new Person();
- 构造函数(Person):就是专门用来生成实例对象的函数;
- 原型:Person.prototype就是原型,它是一个对象,也称它为原型对象;作用就是共享属性和方法;
- 原型链:原型与原型层层链接的过程;
每一个构造函数(Person)都有一个原型对象(prototype);每个原型对象都包含一个指向构造函数的指针(constructor);每个实例都包含一个指向原型的内部指针(__proto__)。
Person.prototype === person.__proto__ === new Person().__proto__
Person.prototype.constructor === person.__proto__.constructor === Person

原型链图

原型链查找方法
如果试图引用对象(实例person)的某个属性或方法:
(1)首先在实例对象内部寻找该,直至找不到;
(2)接着在该对象的原型(person.__proto__)里去找这个属性;
(3)然后会在上级的原型对象里去找...直至Object的原型对象
new过程
(1)创建一个空对象;
(2)将该空对象的原型指向构造函数的原型(obj.__proto__=Person.prototype);
(3)重新绑定this,使构造函数的this指向新对象(Person.call(this));
(4)开始执行构造函数内部代码。
手动实现new操作:
function createNew() {
// 1. Array.from(arguments).shift();转换成数组使用数组的方法shift将第一项弹出
// 2.[].shift().call(arguments); // 通过call() 让arguments能够借用shift方法
let Constructor = Array.from(arguments).shift();
//创建一个空对象
let obj = {};
//将该空对象的原型属性指向构造函数的原型
obj.__proto__ = Constructor.prototype;
//将构造函数的this指向该空对象
Constructor.call(obj, ...arguments);
return obj;
}
new命令总是返回一个对象,如果构造函数内部有return一个对象,new命令会返回return语句指定的对象;否则,返回this对象; 对普通函数(内部没有this关键字的函数)使用new命令,则会返回一个空对象
继承
1、原型链继承
基本思想: 将父类的实例作为子类的原型
不足:1.无法实现多继承;2.来自原型对象的所有属性被所有实例共享(来自原型对象的引用属性是所有实例共享的);3.创建子类实例时,无法向父类构造函数传参
function Person(name) {
this.name = name;
this.sleep = function() {
return this.name + ' is sleeping';
}
}
Person.prototype.eat = function(food) {
return this.name + ' is eating ' + food;
}
function Strive() {}
Strive.prototype = new Person('Strive');
//使用
let strive = new Strive();
console.log(strive.name); //Strive
console.log(strive.sleep()); //Strive is sleeping
console.log(strive.eat('apple'));//Strive is eating apple
2、构造继承
基本思想:在子类型构造函数的内部调用超类型构造函数.
不足:1.只能继承父类的实例属性和方法,不能继承原型属性/方法;2.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
function Strive() {
Person.call(this);
//other code
}
3、实例继承
基本思想:为父类实例添加新特性,作为子类实例返回
function Strive() {
var instance = new Person();
instance.attr = '';
instance.method = function(){};
return instance;
5、组合继承 基本思想:使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承
不足:调用了两次父类构造函数,生成了两份实例
function Strive() {
Person.call(this);
//other code
}
Strive.prototype = new Person();
Strive.prototype.constructor = Strive;
6、寄生组合继承
function Strive() {
Person.call(this);
//other code
}
Strive.prototype = Object.create(Person.prototype);
Strive.prototype.constructor = Strive;
7.es6 class实现继承
class Person {
constructor(name) {
this.name = name;
}
sleep() {
return this.name + ' is sleeping';
}
}
class Strive extends Person {
constructor(name) {
super(name);
}
eat(food) {
return this.name + ' is eating ' + food;
}
}
let strive = new Strive('Strive');
类和构造函数的区别:
- 类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行;
- 类的所有实例共享一个原型对象;
- 类的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。
Object.create(proto, propertiesObject)
使用指定的原型proto对象及其属性propertiesObject去创建一个新的对象,proto 是必填参数,就是新创建出来的对象的原型 (新对象的 __proto__属性指向的对象)
手动实现
var objectCreate = function(proto) {
function Fn(){}
Fn.prototype = proto;
retuen new Fun();
}
Object.create与new的区别
