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={ ...
随机推荐
- Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
本文是 Spring Boot 整合数据持久化方案的最后一篇,主要和大伙来聊聊 Spring Boot 整合 Jpa 多数据源问题.在 Spring Boot 整合JbdcTemplate 多数据源. ...
- 正则表达式 第五篇:C# 正则元字符
本文整理C#正则表达式的元字符,正则表达式是由字符构成的表达式,每个字符代表一个规则,表达式中的字符分为两种类型:普通字符和元字符.普通字符是指字面含义不变的字符,按照完全匹配的方式匹配文本,而元字符 ...
- Session,Token,Cookie相关区别
1. 为什么要有session的出现? 答:是由于网络中http协议造成的,因为http本身是无状态协议,这样,无法确定你的本次请求和上次请求是不是你发送的.如果要进行类似论坛登陆相关的操作,就实现不 ...
- windows 10 上源码编译boost 1.66.0 | compile boost 1.66.0 from source on windows 10
本文首发于个人博客https://kezunlin.me/post/854071ac/,欢迎阅读! compile boost 1.66.0 from source on windows 10 Ser ...
- [ch02-02] 非线性反向传播
系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 2.2 非线性反向传播 2.2.1 提出问题 在上面的线 ...
- 数据类型-Java基础一-初学者笔记
初学者笔记 1.Java中的两种类型 在java源代码中,每个变量都必须声明一种类型(type). 有两种类型:primitive type和reference type.引用类型引用对象(ref ...
- 新闻实时分析系统 SQL快速离线数据分析
1.Spark SQL概述1)Spark SQL是Spark核心功能的一部分,是在2014年4月份Spark1.0版本时发布的. 2)Spark SQL可以直接运行SQL或者HiveQL语句 3)BI ...
- Selenium+Java(三)Selenium元素定位
前言 使用Selenium做元素定位的时候,需要用到HTML的知识,所以最好是能懂得HTML的基本知识. 一.页面元素的查看(以百度为例) 打开IE浏览器,点击F12进入开发者模式,点击图中红圈圈中的 ...
- Dubbo实现登陆
一.目录展示 二.dubbo_logins_service 2.1 实体类和service层 2.2 logins实体类 package com.login.entity; import java.i ...
- pymongo的基本操作和使用
MongoDB简介 MongoDB是一个开源的文档类型数据库,它具有高性能,高可用,可自动收缩的特性.MongoDB能够避免传统的ORM映射从而有助于开发. 文档 在MongoDB中,一行纪录就是一个 ...