JS的继承
拖了很久的JS继承终于来个总结了T^T
本篇文章参考阮一峰老师的博文。一共有三篇。
一、先说一下prototype对象
function Cat(name, age){ this.name = name; this.age = age; this.speak = function () { console.log(this.name + ' miao'); } } var cat1 = new Cat('Tom', 1); var cat2 = new Cat('John', 2); console.log(cat1.speak()); // Tom miao console.log(cat2.speak()); // John miao
上面代码中的两个实例,cat1 和 cat2 都有自己的name属性,age属性,speak方法,但是其实speak方法实可以共用的,这样就会造成了资源浪费。避免这种浪费,我们可以把 speak 方法写入构造函数的 prototype 对象中。
function Cat(name, age){ this.name = name; this.age = age; } Cat.prototype.speak = function(){ console.log(this.name + ' miao'); } var cat1 = new Cat('Tom', 1); var cat2 = new Cat('John', 2);
将可以共享的方法挂载在原型对象上,就可以避免出现内存浪费的现象了
Cat.prototype.speak = function() { console.log(this.name + ' miao'); } Cat.prototype.eat = 'fish'; cat2.prototype.eat = 'meat'; // 问题来了,如果我改变其中一个实例的原型上的属性和方法,那么另一个原型会不会收到影响呢
答案是不会!!!
但是,如果修改的是 cat2.__proto__.eat,那么就会对 cat1 有影响了
这里可能有点迷!!!是的,我有点迷~~~~~~~
我是这样子理解的
因为创建实例需要用到 new 操作符,那么 new 中间作了什么妖呢
- 创建了一个新对象
- 将新对象的__proto__属性指向构造函数的原型对象,新对象就新增了构造函数原型对象上的属性和方法
- 将构造函数的this指向替换成新对象,再执行构造函数,这样新对象就新增了构造函数本地的属性和方法了
// 模拟 new var obj = {}; obj.__proto__ = 构造函数.prototype; 构造函数.apply(obj);
那么看会又来的构造函数 Cat,我画了这样一幅图
二、JS继承
- 原型链继承——将父类的实例作为子类的原型
function Animal(name){ this.name = name; } Animal.propotype = { canRun: function(){ console.log(this.name + ' can run.'); } } function Cat(){ this.speck = 'miao'; } Cat.prototype = new Animal('Tom'); Cat.prototype.constructor = Cat;
我觉得应该会有人有和我一样的疑惑。为什么会有Cat.prototype.constructor = Cat的出现。
因为我们把父类Animal的实例作为了子类Cat的原型对象,因此如果没有Cat.prototype.constructor = Cat,Cat.prototype.constructor就会指向Animal,造成继承链的混乱,所以我们需要手动纠正。
2. 构造继承——改变this的指向,用apply或者call方法实现
function Animal(name){ this.name = name; } Animal.prototype = { canRun: function(){ console.log(this.name + ' it can run!'); } } function Cat(name){ Animal.call(this, name); this.speak = 'miao'; }
var cat1 = new Cat('Tom');
这个继承方法有一个不好,就是子类无法继承父类原型上的属性和方法,也就是说 cat1.canRun()会出错。
3. 组合继承——将原型链继承和构造继承结合到一块
function Animal(name){ this.name = name; } Animal.prototype = { canRun: function(){ console.log(this.name + 'is can run!'); } } function Cat(name, age){ Animal.call(this, name); this.speak = 'miao'; this.age = age; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat('Tom', 12);
原文地址:https://www.cnblogs.com/pingzi-wq/p/11531189.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 数组属性和方法
- Qt音视频开发8-ffmpeg保存裸流
- PyTorch6:nn.Linear&常用激活函数
- Python制作图片验证码?也就三行代码罢了
- 小技巧整理(一)
- 20个能够有效提高 Pandas数据分析效率的常用函数,附带解释和例子
- 4.深入k8s:持久卷PV、PVC及其源码分析
- 5.深入k8s:StatefulSet控制器及源码分析
- 简介机器学习中的特征工程
- 在机器学习回归问题中,你应该使用哪种评估指标?
- 6.深入k8s:守护进程DaemonSet及源码分析
- 无所不能的Embedding 1 - Word2vec模型详解&代码实现
- 【JS】676- 1.1w字 | 初中级前端 JavaScript 自测清单 - 2
- matplotlib基础绘图命令之imshow
- 聊聊dubbo-go的broadcastCluster
- 爬取博客园文章