创建对象的方法

  • 字面量创建
  • 构造函数创建
  • 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);
  1. 创建一个新的对象 obj;
  2. 将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
  3. Base函数对象的this指针替换成obj, 相当于执行了Base.call(obj);
  4. 如果构造函数显示的返回一个对象,那么则这个实例为这个返回的对象。 否则返回这个新创建的对象

类的声明

// 普通写法
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基础-原型链和继承的更多相关文章

  1. 怎么理解js的原型链继承?

    前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...

  2. Js基础知识(二) - 原型链与继承精彩的讲解

    作用域.原型链.继承与闭包详解 注意:本章讲的是在es6之前的原型链与继承.es6引入了类的概念,只是在写法上有所不同,原理是一样的. 几个面试常问的几个问题,你是否知道 instanceof的原理 ...

  3. 小谈js原型链和继承

    原型(prototype)在js中可是担当着举足轻重的作用,原型的实现则是在原型链的基础上,理解原型链的原理后,对原型的使用会更加自如,也能体会到js语言的魅力. 本文章会涉及的内容 原型及原型对象 ...

  4. JS原型链与继承别再被问倒了

    原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...

  5. js原型链与继承(初体验)

    js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询 ...

  6. 深入理解JS原型链与继承

    我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...

  7. js 原型链和继承(转)

    在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var ob ...

  8. Js笔记(对象,构造函数,原型,原型链,继承)及一些不熟悉的语法

    对象的特性: 1.唯一标识性,即使完全不一样的对象,内存地址也不同,所以他们不相等 2.对象具有状态,同一个对象可能处在不同状态下 3.对象具有行为,即对象的状态可能因为他的行为产生变迁 Js直到es ...

  9. Js中的对象、构造函数、原型、原型链及继承

    1.对象 在传统的面向过程的程序设计中,会造成函数或变量的冗余.而JS中对象的目的是将所有的具有相同属性或行为的代码整合到一起,形成一个集合,这样就会方便我们管理,例如: var person1={  ...

随机推荐

  1. ansible-template

    template简介 template功能: 根据模板文件动态生成对应的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 ansible的template模板使 ...

  2. 使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流

    本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu) ...

  3. Java虚拟机详解(九)------类文件结构

    我们知道计算机是由晶体管.电路板等组装而成的电子设备,而这些电子设备其实只能识别0与1的信号. 那么问题来了,我们在操作系统上编写的Java代码(由字母.数字等各种符号组成),打包后部署到服务器上,是 ...

  4. web前端面试题总结(html、css)

    1.对 WEB 标准以及 W3C 的理解与认识? 参考: 标签闭合.标签小写.不乱嵌套.提高搜索机器人搜索几率.使用外 链 css 和 js 脚本. 结构行为表现的分离.文件下载与页面速度更快.内容能 ...

  5. (三)OpenStack---M版---双节点搭建---Keystone安装和配置

    ↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 1.创建keystone数据库 2.创建随机密码作为管理员令牌 3.安装openstack-ke ...

  6. 基于loghub的消息消费延迟监控

    我们可以把loghub当作一个消息中间件来使用.如果能知道当前的消费进度,自然好了,否则消费情况一无所知,总是有点慌! loghub消费分两种情况,一是普通消费,二是消费组消费: 消费组消费,logh ...

  7. Scala学习笔记三

    scala变量理解: package com.cxy.scala object Hello { def main(args: Array[String]): Unit = { println(&quo ...

  8. sql server建库建表(数据库和数据表的常用操作)

    数据库和数据表 (开发常用 操作) 一,数据库的创建 一个SQLServer 是由两个文件组成的:数据文件(mdf) 和日志文件(ldf),所以我们创建数据库就是要为其指定数据库名.数据文件和日志文件 ...

  9. CentOS 7 Nginx部署.NET Core Web应用

    部署.NET Core运行时 必要前提 在安装.NET Core前,需要注册Microsoft签名秘钥并添加Microsoft产品提要,每台机器只需要注册一次,执行如下命令: sudo rpm -Uv ...

  10. ThinkPHP多表查询之join方法

    现在的目的是要把article_category中的name字段导入到article中去 表yz_article如下 表yz_article_category如下