# Javascript学习笔记 **Repository Path**: wang-junjie99/javascript_notes ## Basic Information - **Project Name**: Javascript学习笔记 - **Description**: 誓死学会Javascript系列,一系列关于Javascript难点的难点分析、概括、总结 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-03 - **Last Updated**: 2021-04-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、继承 ## 继承的6种方式 - ### 原型链继承 ###### 关键: ​ 新实例的prototype=父类的实例 ###### 优点: ​ 1.新实例可继承的属性:实例的构造函数属性,父类构造函数属性,父类的prototype属性(注意:不能-继承-父类实例的属性) ###### 缺点: ​ 1.新实例不能向父类构造函数传参 ​ 2.继承单一 ​ 3.所有新实例共享父类实例的属性 (因为prototype上的属性共享,一个新实例改变prototype对象上的属性,另一个新实例prototype属性也会改变) `child1.names.push('yayu');` `console.log(child1.names); // ["kevin", "daisy", "yayu"]` `var child2 = new Child();` `console.log(child2.names); // ["kevin", "daisy", "yayu"]` ------ ###### 示例代码: `function Parent() {` ​ `this.name = "巴拉巴拉"` ​ `}` `Parent.prototype.sayhi = function () {` ​ `console.log(this.name)` ​ `}` `function Child() { }` `Child.prototype = new Parent()` `var child1 = new Child()` `child1.sayhi()` - ### 构造函数继承 ###### 关键: ​ 用.call或.apply改变this的指向,将父类构造函数引入子类构造函数(在子类函数中做父类函数的自执行,相当于复制) ###### 优点: ​ 1.避免了引用类型的属性被所有实例共享 ​ 2.子函数可以向父函数传参 ​ 3.解决了原型链继承方式的3个缺点 4.可以继承多个构造函数=>.call多个 ###### 缺点: ​ 1.只能继承父类构造函数的属性 ​ 2.无法实现构造函数的复用(每次都要重新调用) ​ 3.每个新实例都有父类构造函数的副本,臃肿(不符合DRY规则,Don't repeat yourself) ------ ###### 示例代码: `function Parent() {` ​ `this.name = "巴拉巴拉"` ​ `this.colors = ["yellow", "blue", "purple"]` ​ `}` `Parent.prototype.sayhi = function () {` ​ `console.log(this.name)` ​ `}` `function Child(age) {` ​ `Parent.call(this)` ​ `this.age = age` ​ `}` `var child1 = new Child(16)` `var child2 = new Child(18)` `child1.colors.push("red")` `console.log(child1.name)//巴拉巴拉` `console.log(child2.name)//巴拉巴拉` `console.log(child1.colors)//(4) ["yellow", "blue", "purple", "red"]` `console.log(child2.colors)//(3) ["yellow", "blue", "purple"]` - ### 组合继承(原型链+构造函数)-常用 ###### 关键: ​ 结合两种模式优点:传参和复用 ###### 优点: ​ 1.可以继承了父类原型上的属性,可传参可复用 ​ 2.每个新实例引入的构造函数是私有的 ###### 缺点: ​ 1.调用两次父类构造函数(耗内存),子类的构造函数会代替原型上的父类构造函数 ------ ###### 示例代码: `function Parent() {` ​ `this.name = name` ​ `this.colors = ["yellow", "blue", "purple"]` ​ `}` `Parent.prototype.sayhi = function () {` ​ `console.log(this.name)` ​ `}` `function Child(name, age) {` ​ `Parent.call(this, name)//第二次调用` ​ `this.age = age` ​ `}` `Child.prototype = new Parent()//第一次调用` `var child1 = new Child("张三", 16)` `var child2 = new Child("李四", 18)` `console.log(child1.name)` `console.log(child2.name)` `console.log(child1.age)//16` `console.log(child2.age)//18` - ### 原型式继承 ###### 关键: ​ 用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了可以随意增添属性的实例或对象,object.create()的原理 ###### 优点: ​ 1.类似于复制一个对象,用函数进行包装 ###### 缺点: ​ 1.所有实例都会继承原型上的属性。 ​ 2.无法实现复用(新实例的属性是后加的) ------ ###### 示例代码: `function createObj(o) {//也是ES6以后,Object.create()方法的原理` ​ `function F() { }` ​ `F.prototype = o;` ​ `console.log(o._proto_ === Object.prototype)//false` ​ `console.log(F.prototype.constructor === Object)//true` ​ `return new F()` ​ `}` `var person = {` ​ `name: "张三",` ​ `friends: ["李四", "丁一"]` ​ `}` `var person1 = createObj(person)` `//var person2 = createObj(person)` `person1.name = "person1"` `//console.log(person2.name)//张三` `person1.friends.push("赵五")` `//console.log(person2.friends)//(3) ["李四", "丁一", "赵五"]` `//console.log(person)//{name: "张三", friends: Array(3)}` `person1.friends=["大佬"]` `//console.log(person1.friends)//["大佬"]` `//console.log(person.friends)//(3) ["李四", "丁一", "赵五"]` - ### 寄生式继承 ###### 关键: ​ 给原型式继承套个函数 ###### 优点: ​ 1.没有自定义类型,只是套了个壳子返回对象,这个函数就成了创建的新对象 ###### 缺点: ​ 1.没用到原型,无法复用 ------ ###### 示例代码: `var obj = {` ​ `name: "张三",` ​ `friends: ["李四", "王五"]` ​ `}` `function createObj(o) {` ​ `function F() { }` ​ `F.prototype = o` ​ `return new F()` ​ `}` `function Child() { }` `var child1 = new createObj(obj)` `var child2 = Object.create(obj)` `console.log(child1.name)//张三` `console.log(child2.name)//张三` `function createChild(o){ //核心:` ​ `var newobj = createObj(o) //创建对象,等价于Object.create(o)` ​ `newobj.sayhi=function(){ //增强对象` ​ `console.log("hi")` ​ `}` ​ `return newobj //指定对象` ​ `}` `var p1 = createChild(obj)` `p1.sayhi()//hi` - ### 寄生组合式继承-常用 ###### 关键: ​ 解决了组合继承调用两次父类构造函数的问题 ------ ###### 示例代码: `function Parent(name) {` ​ `this.name = name` ​ `this.colors = ["red", "blue", "green"]` ​ `}` `Parent.prototype.sayhi = function () {` ​ `console.log(this.name)` ​ `}` `function Child(name, age) {` ​ `Parent.call(this, name)` ​ `this.age = age` ​ `}` `function createObj(o) {` ​ `function F() { }` ​ `F.prototype = o` ​ `return new F()` ​ `}` `//Child.prototype=new Parent()换成以下内容` `function prototype(child, parent) {` ​ `var prototype = createObj(parent.prototype)` ​ `prototype.constructor = child` ​ `child.prototype = prototype` ​ `}` `prototype(Child, Parent)` `var child1 = new Child("小白", 16)` `console.log(child1)//Child {name: "小白", colors: Array(3), age: 16}`