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

本文章会涉及的内容

  • 原型及原型对象
  • 原型链(JavaScript核心部分)
  • 类的继承
  • instanceof
  • constructor

我们先用一个构造器来实现一个构造函数:

function A(){
this.mark = "A";
this.changeMark = function(){
this.mark += "_changed";
}
} A.prototype.mark2 = "A2";
A.prototype.changeMark2 = function(){
this.mark2 += "_changed";
} var a = new A();
var a2 = new A(); //下面则说明构造函数实例化后,分配着不同的实例对象,互不相关
console.log(a.mark); //"A"
console.log(a2.mark); //"A"
a.changeMark(); //使用实例对象中的方法
console.log(a.mark); //"A_changed"
console.log(a2.mark); //"A" //下面则说明了new操作符的一项作用,即将原型中的this指向当前对象,
//在a.changeMark2执行时,changMark2中的方法先找 this.mark2 的值,
//但是实例对象this中没有mark2值,则在原型链(后面会介绍)向上寻找,得到A原型对象中的mark2值,
//在赋值时,将修改后的值添加在了a实例中。
//总:虽然调用的是prototype方法,但是不会对prototype属性做修改,只会说是在实例中新增属性,但是在使用时,会最使用最近得到的属性(在后面原型链中可以加以理解)
console.log(a.mark2); //"A2"
console.log(a2.mark2); //"A2"
a.changeMark2(); //使用原型链中的方法
console.log(a.mark2); //"A2_changed"
console.log(a2.mark2); //"A2"

为什么a可以使原型中的changeMark2方法?这就和js巧妙的原型链相关,在Firefox中我们可以打印出对象并可查看到对象下面的__proto__。

我们把上面的过程用流程图来表示:

只有构造函数才会有prototype属性,而实例化出来的对象会拥有__proto__,而不会有prototype。

就像上图画的那样,两个实例化的对象都通过__proto__属性指向了A.prototype(即构造函数的原型对象)

而原型对象的__proto__指向Object对象,就像a.toString()的toString方法就是存在于Object原型对象(Object.prototype)中。

so:当使用对象的方法或属性时,对象会在一步一步通过__proto__向上寻找,找到最近的则是最终的获取到的方法或属性。

  ————这就是js中的原型链。

就像图上看到的一样,所有对象的原型链最终都指向了Object对象,而Object的原型对象(Object.prototype)是为数不多的不继承自任何属性的对象,即Object.prototype没有__proto__,是原型链的顶峰。

通过上面我们可以了解到,当我们对A.prototype或Object.prototype添加属性或方法时,在a和a2实例中都会查看到该属性或方法,因为这两个实例都通过原型链与A和Object的原型对象相连。

 再来看看原型对象和原型链在继承方面的实现:

再构造一个函数A和一个函数B,并让B继承A,如下:

function A(mark){
this.mark = mark;
}
A.prototype.getMark = function(){
return this.mark;
} function B(mark){
  this.mark = mark
} //var temp = new A("A");
//B.prototype = temp;
//上面语句和下语句作用相同 B.prototype = new A("A"); //实例化一个A,其赋值于B.prototype
                //我们知道了原型链,这样做就是将B的原型对象与A的原型对象通过原型链(__proto__)连接起来
                //以实现继承 var b = new B("B"); console.log(b.mark); //B, 结果如上面原型链分析的那样,向上找到最近的属性,则为b实例中的mark:"B"

其中的结构示意大概如下图:

这时我们可以看到,在B.prototype中是没有constructor的,因为B.prototype只是简单的new A("A")对象赋值的结果。

在js中的constructor有什么作用呢?如:

var arr = new Array();
arr instanceof Array; //true
arr.constructor === Array; //true function TEMP(){
}
var temp = new TEMP();
temp instanceof TEMP; //true
temp.constructor === TEMP; //true

引用《JavaScript权威指南》中的对于constructor的解释为:对象通常继承的constructor均指代它们的构造函数,而构造函数是类的“公共标识”。即constructor可用来判断对象所属的类。

 

在上面的小例子中,用instanceof也可判断对象的类,但是有自身的缺陷,instanceof的实现方法为:

instanceof不会去检查temp是不是由TEMP()构造函数初始化的,面是判断temp是否继承自TEMP.prototype,这样,范围就宽了很多。

如在上面的大例中,使用

b instaceof B //true 因为在b的原型链中可以找到B.prototype对象

b instaceof A //true 在b的原型链中也可以找到A.prototype对象

可以说instanceof是用来检测继承关系的。

而当

console.log(b.constructor) //function A()
//因为在b的原型链中,最近的constructor就是A.prototype中有constructor指向了构造函数A();

但我们知道的b是属于B类的,那最后所以要做的就是:

B.prototype.constructor = B; //将constructor指向自身的构造函数

var new_b = new B("B");
console.log(new_b.constructor) //function B() 

这样,一个完整的类继承才完成了。

最后附上一个完整继承后的结果图:

第一次写长文,如有问题,还请大家指出。

转载请注明出处,谢谢。

Finish.

小谈js原型链和继承的更多相关文章

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

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

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

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

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

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

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

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

  5. 【转】js原型链与继承

    原文链接:https://blog.csdn.net/u012468376/article/details/53127929 一.继承的概念 ​ 继承是所有的面向对象的语言最重要的特征之一.大部分的o ...

  6. js原型链和继承

    在了解js原型链之前构造函数.原型对象.对象实例这几种概念必须要明白. 1. 创建对象有几种方法 //原型链指向objectvar o1={name:'o1'}; var o11=new Object ...

  7. js 原型链与继承

    var A = function(){ this.name="xiaoming"; } A.prototype.age=9; var a = new A(); console.lo ...

  8. js原型链、继承、this指向等老生常谈却依然不熟的知识点——记录解析

    开始记录学习过程—— 很详细的解析过程——https://juejin.im/post/5c72a1766fb9a049ea3993e6 借鉴阅读——https://github.com/KieSun ...

  9. 再谈javascriptjs原型与原型链及继承相关问题

    什么是原型语言 只有对象,没有类;对象继承对象,而不是类继承类. “原型对象”是核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以 ...

随机推荐

  1. servlet request getQueryString 汉字的URI编码如何转码

    JavaScript中编码有三种方法:escape.encodeURI.encodeURIComponent,地址栏中那些%XX就是汉字对应的字节被encodeURI编码格式转了.一个字节对应一个% ...

  2. JDBC JdbTemplate&NamedParameterJdbcTemplate(Spring工具类)

    使用该工具类需要从spring开发包中导入spring.jar和commons-logging.jar,这个模板是线程安全的.   JdbcTemplate: public class JdbcTem ...

  3. mosquitto 启动命令

    启动命令 mosquitto [-c config file] [ -d | --daemon ] [-p port number] [-v] -c 后面跟的是启动mosquitto可以调整的参数,比 ...

  4. python --curl重定向到文件范例

      import sys import os import subprocess import time start = time.time() old=sys.stdout f=open('test ...

  5. IntelliJ IDEA 学习(一):IntelliJ IDEA15 破解方法(已验证)

    新的破解方法: 1.进到文件夹中:C:\Windows\System32\drivers\etc ,找到hosts文件,用记事本编辑 2.如果没有找到hosts文件,可在查看设置中勾选“显示隐藏的项目 ...

  6. 阿里云 部署并开启nodejs应用

    1.下载资源  $ wget https://nodejs.org/dist/v8.11.2/node-v8.11.2-linux-x64.tar.xz 2.xz解压 $ xz -d node-v8. ...

  7. java中GET方式提交和POST方式提交

    java中GET方式提交的示例: /** * 获取关注列表; * @return */ @SuppressWarnings("unchecked") public static A ...

  8. 逆向project第005篇:跨越CM4验证机制的鸿沟(下)

    一.前言 本文是逆向分析CM4系列的最后一篇,我会将该游戏的序列号验证机制分析完成,进而编写出注冊码生成器. 二.分析第二个验证循环 延续上一篇文章的内容,来到例如以下代码处: 图1 上述代码并没有特 ...

  9. C++ 模板详解 肥而不腻

    C++模板 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数.返回值取得任意类型. 模板是一种对类型进行参数化的工具: 通常有 ...

  10. pyspark采用python3开发

    现在时间2017-04-17. python版本3.5支持pyspark python3.6目前还不支持 做法简单,只需要在bin/pyspark中增加 export PYSPARK_PYTHON=p ...