js-对象几种继承方式
时间:2021-08-11
本文章向大家介绍js-对象几种继承方式,主要包括js-对象几种继承方式使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
注意:
- constructor总是指向类的构造函数
- __proto__指向父类的原型对象
- instanceof可以判断构造函数的继承关系
一、原型链继承
function Father(name) {
this.name = name;
this.color = ['red', 'blue'];
}
Father.prototype.getName = function () {
console.log(this.name)
}
function Child() { }
Child.prototype = new Father();
Child.prototype.constructor = Child;
var son1 = new Child('ming');
var son2 = new Child('wei');
son1.color.push('white');
son2.color; //['red','blue','white']
缺点:对于复杂数据类型color,多个实例对引用的操作会被篡改
二、借用构造函数继承
function Father(name) {
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name)
}
function Son(name) {
Father.apply(this, arguments);
}
var son = new Son('ming');
console.log(son.getName()) // son.getName is not a function
缺点:父类原型链上的属性和方法无法获取
三、组合继承(伪经典继承)
function Father(name) {
this.name = name;
this.color=['red','blue'];
}
Father.prototype.getName = function() {
console.log(this.name)
}
function Child(name) {
Father.apply(this, arguments);
}
Child.prototype = new Father();
Child.prototype.constructor = Child;
var son = new Child('ming');
console.log(son.color);
son.color.push('white')
var son2 = new Child('wei');
console.log(son2.color) //['red','blue']
基本ok,除了new Father()那个地方会多写一遍属性和方法,差不多还行
四、原型式继承(道爷-2006)
var Person = {
name: 'ming',
color: ['red', 'blue']
}
function object(obj) {
function F() { };
F.prototype = obj;
return new F();
}
var son1 = object(Person);
var son2 = object(Person);
son1.name = 'wei';
son1.color = ['white'];
console.log(son2.color); // ['red','blue','white']
缺点很明显:
1,原型实例指向的引用相同,可能存在篡改
2,不能传递参数
另:object方法已经由Object.create()实现
五、寄生式继承,(道爷有点皮)
创建一个函数,在内部构造新的属性和方法,以增强对象(原型式继承的加强版)
var Person = {
name: 'ming',
color: ['red', 'blue']
}
function object(obj) {
function F() { };
F.prototype = obj;
return new F();
}
function createSon(obj) {
var son = object(obj);
console.log(son)
son.say = function () {
console.log('Hello,' + this.name)
}
return son;
}
var son1 = createSon(Person);
console.log(son1.name)
缺点很明显:
1,原型实例指向的引用相同,可能存在篡改
2,不能传递参数
六、寄生组合式继承(借用构造函数继承+寄生式继承)
function object(obj) {
function F() { };
F.prototype = obj;
return new F();
}
function inheritPerson(Person, Son) {
var pro = object(Person.prototype);
Son.prototype.constructor = Son;
Son.prototype = pro;
}
function Person(name) {
this.name = name;
this.color = ['red', 'blue'];
}
Person.prototype.say = function () {
console.log('Hello,' + this.name)
}
function Son(name, age) {
Person.call(this, name);
this.age = age;
}
inheritPerson(Person, Son);
Son.prototype.getAge = function () {
console.log(this.age);
}
var child1 = new Son('ming', 20);
var child2 = new Son('wei', 30);
child1.say() // ming
child1.color.push('white');
console.log(child2.color) //['red','blue']
这个是es5的终极解决方案
七、混入方式继承多个对象
function Father1(name) { this.name = name }
function Father2(age) { this.age = age }
function Son(name, age) {
Father1.call(this, name);
Father2.call(this, age);
}
Son.prototype = Object.create(Father1.prototype);
Object.assign(Father1.prototype, Father2.prototype);
Son.prototype.constructor = Son;
var son1 = new Son('ming', 20);
console.log(son1)
这个实际上是寄生组合式继承的加强版
八、class继承
class Person {
constructor(name) {
this.name = name
}
say() {
console.log(this.name)
}
}
class Son extends Person {
constructor(name) {
super(name)
}
}
使用babel转义为es5之后:
"use strict";
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
var Person =
function () {
function Person(name) {
this.name = name;
}
var _proto = Person.prototype;
_proto.say = function say() {
console.log(this.name);
};
return Person;
}();
var Son =
function (_Person) {
_inheritsLoose(Son, _Person);
function Son(name) {
return _Person.call(this, name) || this;
}
return Son;
}(Person);
总结
- 类方法调用时不会变量提升:
var p = new P(); // Cannot access 'P' before initialization class P{}
- es6的继承,实际上是先创建父类的实例对象this,然后再用子类的构造函数修改this,因此在子类的contructor中要调用父类的super(),否则要报错。
原文地址:https://www.cnblogs.com/zhangct456/p/15129507.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决Laravel 不能创建 migration 的问题
- 使用tp框架和SQL语句查询数据表中的某字段包含某值
- Laravel框架中集成MongoDB和使用详解
- thinkphp5 模型实例化获得数据对象的教程
- 浅谈laravel框架sql中groupBy之后排序的问题
- php 比较获取两个数组相同和不同元素的例子(交集和差集)
- Laravel 5.5 异常处理 & 错误日志的解决
- Laravel 框架返回状态拦截代码
- PHP getID3类的使用方法学习笔记【附getID3源码下载】
- PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
- 浅谈laravel 5.6 安装 windows上使用composer的安装过程
- PhpStorm 如何优雅的调试Hyperf的方法步骤
- 在TP5数据库中四个字段实现无限分类的示例
- 详解Laravel设置多态关系模型别名的方式
- tp5修改(实现即点即改)