### 原型链的理解
#### 概念
+ javascript每一个对象**包括原型对象**都有一个内置的`proto`属性指向创建他的函数对象的原型对象,即`prototype`属性
#### 作用
+ 实现对象的继承
### 理解
1.函数对象
+ 在javascript中,函数就是对象
2.原型对象
+ 当定义一个函数对象的时候,会包含一个预定的属性,`prototype`,这就属性称之为原型对象
3.\__proto__
+ javascript 在创建对象的时候,都会有一个\_proto\_的内置属性,用于指向创建它的函数对象的`prototype`。原型对象也有\_proto\_ 属性。因此在不断的指向中,形成了原型链。
4.new
+ 当使用new关键字去调用构造函数就相当于执行啦
5.constructor
+ 原型对象prototype上都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用
### 继承
+ **构造函数绑定**
> 使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:
```javascript
function test(name,height) { this.name = name this.height= height }; function trys(age){ this.age = age test.apply(this,["张三","180cm"]) //apply(this,argument)第一个参数为改变this指向,第二个参数为一个伪数组每一项对应 调用apply的函数的形参。 //call(this,name,height) 第一个参数为this,后面参数为调用call的函数的形参。 } let person = new trys; person.age = "18" console.log(person) ```
+ prototype模式
```javascript
function test(name,height) { this.name = name this.height= height this.do=function(hobby){ console.log("我是"+this.name+"我今年"+this.age+"岁"+"身高"+this.height+"我喜欢"+hobby) } }; function trys(age){ this.age = age } trys.prototype =new test trys.prototype.constructor = trys; // trys.prototype =new test 将trys的constructor 属性指向了test,每一个实例对象也会有一个constructor属性默认指向prototype的constructor 属性,person.constructor==test 所以需要将trys的constructor属性重新指回trys let person = new trys; person.name = "张三" person.age = 18 person.height = 180 person.do("打羽毛球") console.log(person)```![](http://p0zfk1qh0.bkt.clouddn.com/markdown001.png)+ 直接继承prototype
> 是对第二种方法的改进。由于person对象中,不变的属性都可以直接写入person.prototype。所以,我们也可以让man()跳过 person(),直接继承person.prototype。```javascript
function person (){ } person.prototype.skill = "开车" function man(){ this.hobby = "泡妞" } man.prototype = person.prototype; man.prototype.constructor = man; let xiaoming = new man ; console.log(xiaoming.skill);```+ 利用空对象作为中介> 用第三种方法会改变person的constructor 的指向 所以有了这种方法 定义一个空的
> 对象作为中介```javascript
function person (){ } person.prototype.skill = "开车" function man(){ this.hobby = "泡妞" } function F (){ } F.prototype =person.prototype man.prototype = new F() man.prototype.constructor = man; let xiaoming = new man ;```> 我们将上面的继承封装```javascript
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }```+ 拷贝继承>把父对象的所有属性和方法,拷贝进子对象
``` javascript
function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; }``` + 非构造函数继承```javascript let person = { skill:"行走" } let xiaomming = { age:"18" } function object(o) { function F() {} F.prototype = o; return new F(); } let xiaoming = object(person) console.log(xiaoming.skill) //行走```+ 浅拷贝***这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。***
```javascript
let person = { skill:"行走" } let xiaomming = { age:"18" }function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; //遍历p对象,将p对象的每一个属性 都赋值给c对象的每一项 } return c; }let xiaoming = extendCopy(person);console.log(xiaoming.skill)//行走```+ 深拷贝>"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。只要递归调用"浅拷贝"就行了。
``` javascript let person = { skill:"行走" } let xiaomming = { age:"18" } function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; } var xiaoming = deepCopy(person) console.log(xiaoming.skill)```