JavaScript继承解析
栏目: JavaScript · 发布时间: 5年前
内容简介:基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。本篇完。
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
借助构造函数实现继承
- 缺点:无法继承原型链上的属性和方法
function Person () { this.name = 'person1' } Person.prototype.sex = '10' Person.prototype.sayName = function () { alert(this.name) } function Man () { Person.call(this) this.age = '24' } var m1 = new Man() console.log(m1) // Man {name: "person1", age: "24"} (注意:实例自身不存在sex属性和 sayName方法) // m1.sayName() // 报错 (因为原型链上也不存在) 复制代码
借助原型链实现继承
- 缺点:子类共享父类的引用属性
function Father () { this.Farr = [1, 2, 3] } function Child () { } Child.prototype = new Father() var c1 = new Child() var c2 = new Child() console.log(c1.Farr) // [1, 2, 3] console.log(c2.Farr) // [1, 2, 3] c1.Farr.push(4) console.log(c1.Farr) // [1, 2, 3, 4] console.log(c2.Farr) // [1, 2, 3, 4] 复制代码
组合继承
- 优点:子类不会共享父类中的属性,缺点:Mother构造函数被执行两次,无法确定实例直接父类了
function Mother () { console.log('init Mother...') this.Marr = ['a', 'b', 'c'] } function Daughter () { Mother.call(this) // 执行一次Mother构造函数 } Daughter.prototype = new Mother() // 再执行一次Mother构造函数 var d1 = new Daughter() var d2 = new Daughter() console.log(d1.Marr) // ["a", "b", "c"] console.log(d2.Marr) // ["a", "b", "c"] d1.Marr.push('d') console.log(d1.Marr) // ["a", "b", "c", "d"] console.log(d2.Marr) // ["a", "b", "c"] console.log(d2.__proto__.constructor === Mother) // true(期望值是false,因为Daughter才是d2的直接父类) 复制代码
组合继承优化(一)
- 优点:防止调用两次构造函数,缺点:依旧无法确定实例直接父类
function Animal () { console.log('init Animal...') } function Cat () { Animal.call(this) // 执行一次Animal构造函数 } Cat.prototype = Animal.prototype var cat = new Cat() console.log(cat.__proto__.constructor === Animal) // true(期望值是false,因为Cat才是cat的直接父类) 复制代码
组合继承优化(二)
- 解决无法确定实例直接父类问题
function God () { console.log('init Final...') this.name = 'god' } God.prototype.todo = function () { alert('todo') } function Son () { God.call(this) } // Son.prototype = God.prototype Son.prototype = Object.create(God.prototype) // Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ console.log(God.prototype) console.log(Object.create(God.prototype)) Son.prototype.constructor = Son var s = new Son // 无参数时,小括号可以省略 console.log(s) console.log(s.__proto__.constructor === Son) // true (与期望值一直,完美!) console.log(s.__proto__.constructor) // true (与期望值一直,完美!) 复制代码
为什么要用Object.create()方法
- Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
- 使用这个方法,传入null可以创建一个无任何属性的对象(原型上也没有)
- 使用这个方法,会将现有对象放到__proto__属性中,会隐藏现有对象原型上的默认属性和方法,仅仅保留用户自己定义的。
// 普通方法创建对象的对象 console.log({}) // 使用Object.create创建的对象 console.log(Object.create(null)) // 使用Object.create,会将现有对象放到__proto__属性中 function God () { console.log('init Final...') this.name = 'god' } God.prototype.todo = function () { alert('todo') } function Son () { God.call(this) } // Son.prototype = God.prototype Son.prototype = Object.create(God.prototype) Son.prototype.constructor = Son console.log(Son.prototype) 复制代码
-
普通方法创建对象的对象
-
使用Object.create创建的对象
-
使用Object.create()方法实现继承
-
不使用Object.create()方法实现继承
本篇完。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- JavaScript常用6大继承方式解析
- 028.Python面向对象继承(单继承,多继承,super,菱形继承)
- PHP类继承、接口继承关系概述
- 面向对象:理解 Python 类的单继承与多继承
- java入门第二季--继承--java中的继承初始化顺序
- 前端基本功(七):javascript中的继承(原型、原型链、继承的实现方式)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。