JS基础-原型链和继承
创建对象的方法
- 字面量创建
- 构造函数创建
- Object.create()
var o1 = {name: 'value'};
var o2 = new Object({name: 'value'});
var M = function() {this.name = 'o3'};
var o3 = new M();
var P = {name: 'o4'};
var o4 = Object.create(P)
原型
- JavaScript 的所有对象中都包含了一个
__proto__
内部属性,这个属性所对应的就是该对象的原型 - JavaScript 的函数对象,除了原型
__proto__
之外,还预置了 prototype 属性 - 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象的原型
__proto__
。
原型链
任何一个实例对象通过原型链可以找到它对应的原型对象,原型对象上面的实例和方法都是实例所共享的。
一个对象在查找以一个方法或属性时,他会先在自己的对象上去找,找不到时,他会沿着原型链依次向上查找。
注意: 函数才有prototype,实例对象只有有__proto__, 而函数有的__proto__是因为函数是Function的实例对象
instanceof原理
判断实例对象的__proto__属性与构造函数的prototype是不是用一个引用。如果不是,他会沿着对象的__proto__向上查找的,直到顶端Object。
判断对象是哪个类的直接实例
使用对象.construcor
直接可判断
构造函数,new时发生了什么?
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
- 创建一个新的对象 obj;
- 将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
- Base函数对象的this指针替换成obj, 相当于执行了Base.call(obj);
- 如果构造函数显示的返回一个对象,那么则这个实例为这个返回的对象。 否则返回这个新创建的对象
类
类的声明
// 普通写法
function Animal() {
this.name = 'name'
}
// ES6
class Animal2 {
constructor () {
this.name = 'name';
}
}
继承
借用构造函数法
在构造函数中 使用Parent.call(this)
的方法继承父类属性。
原理: 将子类的this使用父类的构造函数跑一遍
缺点: Parent原型链上的属性和方法并不会被子类继承
function Parent() {
this.name = 'parent'
}
function Child() {
Parent.call(this);
this.type = 'child'
}
原型链实现继承
原理:把子类的prototype(原型对象)直接设置为父类的实例
缺点:因为子类只进行一次原型更改,所以子类的所有实例保存的是同一个父类的值。
当子类对象上进行值修改时,如果是修改的原始类型的值,那么会在实例上新建这样一个值;
但如果是引用类型的话,他就会去修改子类上唯一一个父类实例里面的这个引用类型,这会影响所有子类实例
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
function Child() {
this.type = 'child'
}
Child.prototype = new Parent();
var c1 = new Child();
var c2 = new Child();
c1.__proto__ === c2.__proto__
组合继承方式
组合构造函数中使用call继承和原型链继承。
原理: 子类构造函数中使用Parent.call(this);
的方式可以继承写在父类构造函数中this上绑定的各属性和方法;
使用Child.prototype = new Parent()
的方式可以继承挂在在父类原型上的各属性和方法
缺点: 父类构造函数在子类构造函数中执行了一次,在子类绑定原型时又执行了一次
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
function Child() {
Parent.call(this);
this.type = 'child'
}
Child.prototype = new Parent();
组合继承方式 优化1:
因为这时父类构造函数的方法已经被执行过了,只需要关心原型链上的属性和方法了
Child.prototype = Parent.prototype;
缺点:
- 因为原型上有一个属性为
constructor
,此时直接使用父类的prototype的话那么会导致 实例的constructor为Parent,即不能区分这个实例对象是Child的实例还是父类的实例对象。 - 子类不可直接在prototype上添加属性和方法,因为会影响父类的原型
注意:这个时候instanseof是可以判断出实例为Child的实例的,因为instanceof的原理是沿着对象的__proto__判断是否有一个原型是等于该构造函数的原型的。这里把Child的原型直接设置为了父类的原型,那么: 实例.proto === Child.prototype === Child.prototype
组合继承方式 优化2 - 添加中间对象【最通用版本】:
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
function Child() {
Parent.call(this);
this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype); //提供__proto__
Child.prototype.constrctor = Child;
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
封装一个原生的继承方法
/**
* 继承
* @param Parent
* @param Child
*/
function extendsClass(Parent, Child) {
function F() {}
F.prototype = Parent.prototype
Child.prototype = new F()
Child.prototype.constrctor = Child
return Child
}
ES5/ES6 的继承除了写法以外还有什么区别?
- class 声明会提升,但不会初始化赋值。Foo 进入暂时性死区,类似于 let、const 声明变量。
- class 声明内部会启用严格模式。
- class 的所有方法(包括静态方法和实例方法)都是不可枚举的。
- class 的所有方法(包括静态方法和实例方法)都没有原型对象 prototype,所以也没有[[construct]],不能使用 new 来调用。
- 必须使用 new 调用 class。
- class 内部无法重写类名。
JS基础-原型链和继承的更多相关文章
- 怎么理解js的原型链继承?
前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...
- Js基础知识(二) - 原型链与继承精彩的讲解
作用域.原型链.继承与闭包详解 注意:本章讲的是在es6之前的原型链与继承.es6引入了类的概念,只是在写法上有所不同,原理是一样的. 几个面试常问的几个问题,你是否知道 instanceof的原理 ...
- 小谈js原型链和继承
原型(prototype)在js中可是担当着举足轻重的作用,原型的实现则是在原型链的基础上,理解原型链的原理后,对原型的使用会更加自如,也能体会到js语言的魅力. 本文章会涉及的内容 原型及原型对象 ...
- JS原型链与继承别再被问倒了
原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...
- js原型链与继承(初体验)
js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询 ...
- 深入理解JS原型链与继承
我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...
- js 原型链和继承(转)
在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var ob ...
- Js笔记(对象,构造函数,原型,原型链,继承)及一些不熟悉的语法
对象的特性: 1.唯一标识性,即使完全不一样的对象,内存地址也不同,所以他们不相等 2.对象具有状态,同一个对象可能处在不同状态下 3.对象具有行为,即对象的状态可能因为他的行为产生变迁 Js直到es ...
- Js中的对象、构造函数、原型、原型链及继承
1.对象 在传统的面向过程的程序设计中,会造成函数或变量的冗余.而JS中对象的目的是将所有的具有相同属性或行为的代码整合到一起,形成一个集合,这样就会方便我们管理,例如: var person1={ ...
随机推荐
- pat 1027 Colors in Mars(20 分)
1027 Colors in Mars(20 分) People in Mars represent the colors in their computers in a similar way as ...
- hdu 1263 水果 (嵌套 map)
水果Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissio ...
- poj 1001 求高精度幂(Java, BigDecimal, pow, hasNext, stripTrailingZeros, toPlainString)
求高精度幂 Time Limit: 500MS Memory Limit: 10000K Total Submissions: 180325 Accepted: 43460 Descripti ...
- ES6入门十二:Module(模块化)
webpack4打包配置babel7转码ES6 Module语法与API的使用 import() Module加载实现原理 Commonjs规范的模块与ES6模块的差异 ES6模块与Nodejs模块相 ...
- django_1:配置文件
工程下: settings.py(建议设置成如下) DATABASES #数据库配置 DEBUG = True ...
- 开始逆向objc基础准备(一)简单认识一下arm32,以及与x86汇编指令类比
ARM32体系中有31或33个通用寄存器,没有特定的某种态下有r0-r15一共16个寄存器,快速中断态下有另一组r8-r12备份寄存器,在用户态和系统态之外其它态下都各自有一组r13-r14备份寄存器 ...
- Day01第一天 Python基础一
变量 就是将一些运算的中间结果暂时存在内存中,以便后续代码的调用. >命名规则: 1,只能以字母,数字,下划线自由组合,且,不能以数字开头.2,不能是 Python 中的关键字.3,要具有可 ...
- sqlalchemy 源码分析之create_engine引擎的创建
引擎是sqlalchemy的核心,不管是 sql core 还是orm的使用都需要依赖引擎的创建,为此我们研究下,引擎是如何创建的. from sqlalchemy import create_eng ...
- 部署kube-proxy组件
目录 前言 创建kube-proxy证书签名请求 创建和分发 kubeconfig 文件 创建kube-proxy配置文件 分发和创建kube-proxy配置文件 创建和分发 kube-proxy s ...
- Haproxy安装部署文档及多配置文件管理方案
一.部署安装 二.软件配置 三.系统服务 四.日志配置 五.小结 文章目录 最近我在负责一个统一接入层的建设项目,涉及到 Haproxy 和 ospf 的运维部署,本文分享一下我在部署 Haproxy ...