理解原型和原型链。需从构造函数、__proto__属性(IE11以下这个属性是undefined,请使用chrome调试)、prototype属性入手。

JS内置的好多函数,这些函数又被叫做构造函数。如:Object---Array---Function---Date---String---Number---Boolean---Symbol---RegExp....

JS里,所有的对象,都是其构造函数的实例。如{}是Object的一个实例,[]是Array的一个实例。fn() {}是Function的一个实例...

(js的内置对象就不太清楚了。。如Math、JSON。只知道也是Object类型)。

一般情况,我们用对象字面量的方式创建Object的实例。

如:const obj = {}; 这种创建方式是完全等于const obj = new Object();  当然字面量方式是推荐写法。

只要是函数,甭管构造不构造,都有一个prototype属性(指针,其指向函数的原型对象);该属性的值是一个对象,我们管它叫原型对象,其实它就是一个普通对象。对象该有的他都有。它还有个特殊的属性--constructor。属性值就是前面的函数。

关系图:

当调用构造函数创建实例时,实例内部将包含一个属性(指向其构造函数的原型对象的指针),在chrome、ff。这个属性是__proto__。这个属性的值是其构造函数的原型对象。

如上所示,obj是Object构造函数的一个实例,实例上有__proto__属性。这个属性值全等于Object构造函数的原型对象。

多亏有这个__proto__指针,我们在某构造函数的原型对象上定义的属性和方法都能被其所有的实例所共享。

在一些浏览器里(没错,就是IE),这个指针是不可见的。我们可以用 isPrototypeof()方法或者Object.getPrototypeOf()方法来判断实例与原型之间是否存在这种关系。

IE9以下就不支持Object.getPrototypeOf()方法了。

如果实例的 __proto__属性 或者叫 指向构造函数原型对象的指针 指向调用isPrototypeOf()方法的对象(Fn.prototype)。那么这个方法返回值是true。

这里一定要理解,实例的__proto__属性或者叫指向构造函数原型对象的指针是实实在在存在的,只不过有些浏览器给他取了个名字__proto__。有些浏览器没有去定义这个指针的名字。

Object.getPrototypeOf(fn1)方法返回的对象是fn1的构造函数的原型对象。

接下来就是原型链了

在js里。Object类型是基础类型,其他所有的引用类型都继承这个类型。

那么要怎么实现继承呢。

JS实现继承的方式主要就是通过原型链方法。

前面学习时,我们已经得知每个构造函数都有一个原型对象,构造函数的实例有一个指向原型对象的指针。

我们要做的就是。

把另外一个构造函数的实例赋值给原型对象。

首先,我们再定义一个函数Foo,此时Foo.prototype.__proto__ 全等于 Object.prototype;

(原型对象也是对象,自然也会有__proto__指针,如果没有去改它。默认就是指向Object.prototype呦)

接着。把另外一个构造函数的实例赋值给Foo.prototype。

显而易见,根据引用类型值的特性,Foo.prototype 和 fn1指向同一个对象。

这个对象的__proto__属性又指向其构造函数的原型对象。由此Foo函数的原型对象就包含了指向Fn的原型对象的指针。

即:Foo.prototype.__proto__ === Fn.prototype。

如果Fn的原型对象也是另外另外一个函数的实例。。。上述关系仍然成立,如此层层递进。一直指到Object.prototype。

这个对象就比较特殊了。它就没有__proto__属性。Object.prototype.__proto__ === null。原型链到此结束。

上图:

以上定义了两个函数。Person是超类型,Teacher子类型。人可以不是老师,但是老师一定是人嘛。哈哈哈。

属性的继承是通过

构造函数的this指向他的实例。通过call方法。把Person函数的this绑定到Teacher的实例xm,xh上。相当于xm.name = '小明';xh.name = ’小花‘;

方法的继承通过

这步实现了原型链关系。通过向原型链查找,只要存在于原型链上的方法,实例都能用。

确定原型和实例的关系

除了上面的isPrototypeOf()方法外,还有一个方法广为人知。就是使用Instance of 。

用这个操作符测试实例和原型链中出现过的构造函数。结果会返回true。

实现一个简单的instanceof操作符。

1.

 Object.prototype.myInstanceOf = function (Func) {
if (typeof Func !== 'function') {
return false;
}
return Func.prototype.isPrototypeOf(this);
};

2.

 Object.prototype.myInstanceOf = function (Func) {
if (typeof Func !== 'function') return false; function _fn(instance, Func) {
if (instance.__proto__) {
if (instance.__proto__ !== Func.prototype) {
return _fn(instance.__proto__, Func);
} else {
return true;
}
}
return false;
}
return _fn(this, Func);
};

3.

Object.prototype.myInstanceOf = function (Func) {
if (typeof Func !== 'function') {
return false;
}
let _obj = Object.getPrototypeOf(this),
res = false;
while (_obj) {
if (_obj === Func.prototype) {
res = true;
break;
}
_obj = Object.getPrototypeOf(_obj);
}
return res;
};

结果:

也不知道有没有什么边界情况下的错误。。。

累死了。。

javascript原型原型链 学习随笔的更多相关文章

  1. JavaScript作用域、作用域链 学习随笔

    (本文是这些知识点的自我理解.写之余从头回顾,加深理解.取得更多收获之用.) 作用域(scope) 程序设计概念,通常来说,一段程序代码中所用到的名字(JS叫标识符(如变量名.函数名.属性名.参数.. ...

  2. javaScript 原型与原型链学习笔记

    javaScript中,原型是常用到一种方式,它能降低储存占用,写出更高效的代码 原型常用到的则是prototype属性 JavaScript prototype 属性 定义和用法 prototype ...

  3. javaScript系列 [04]-javaScript的原型链

    [04]-javaScript的原型链 本文旨在花很少的篇幅讲清楚JavaScript语言中的原型链结构,很多朋友认为JavaScript中的原型链复杂难懂,其实不然,它们就像树上的一串猴子. 1.1 ...

  4. JavaScript prototype原型和原型链详解

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  5. JavaScript的原型链继承__propt__、prototype、constructor的理解、以及他们之间相互的关系。

    回想自己已经工作了有一段时间了,但是自己对JavaScript的原型链.和继承的理解能力没有到位,最近他们彻底的整理并且复习了一遍. 本案例中部分文案来自网络和书籍,如有侵权请联系我,我只是把我的理解 ...

  6. Javascript的原型链图

    90%的前端或者js程序员或者老师们对Javascript懂得不比这个多 给手机看的 但是这个图里的所有褐色单向箭头链就是Javascript的原型链(颜色标注对理解js原型链很关键) 这图中的各个_ ...

  7. javascript 之原型、原型链-14

    原型 原型是一个对象,每个函数对象(在javascript 之对象中说过函数也是对象 )都有一个属性(prototype)指向这个对象--原型对象,这个对象的作用是让所有对象实例共享原型对象中的属性. ...

  8. 三张图搞懂JavaScript的原型对象与原型链

    对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__proto__混淆,二来它们之间的各种指向实在有些复杂,其实市面上已经有非常多的文章在尝试说清楚,有一张 ...

  9. 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)

    摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...

随机推荐

  1. 四、postman增加断言

    预期和实际结果的判断 预期==实际:用例通过,写到报告里 预期!==实际:用例失败,写到报告里 一.例子演示 相当于首页右侧的10大每天的内容 url:http://www.v2ex.com/api/ ...

  2. MySql存储过程常用的函数

    字符串类 CHARSET(str) //返回字串字符集CONCAT (string2 [,... ]) //连接字串INSTR (string ,substring ) //返回substring首次 ...

  3. windows系统中在jupyter安装虚拟环境内核

    一.在jupyter中安装虚拟环境内核 1.创建Python3虚拟环境 参考本文其他博客 2.进入虚拟环境 3.安装jupyter pip install jupyter 4.添加当前环境到jupyt ...

  4. JavaScript图形实例:图形的旋转变换

    旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...

  5. 【转】 嵌入式C语言编程中Inline函数的应用

    源地址:https://blog.csdn.net/vigour1000/article/details/9622037 有一段儿时间没写写经验笔记了,哎,也是自己这一段时间以来(其实最近一直是这个状 ...

  6. C#本地修改器

    C#本地修改器 C# 制作外挂常用的API C#做外挂的常用API,本人用了很久,基本没发现问题 using System; using System.Collections.Generic; usi ...

  7. go 的基本数据类型和结构

    // 变量命名方式当用两个或两个以上的单词命名变量时,可以将除第一个单词以外的所有单词的首字母大写package 命名方式全部小写不加 _ 布尔类型:bool整型:int8.byte.int16.in ...

  8. noVNC 安装、配置与使用

    最近项目中使用到了远程终端操控,从各方找到了noVNC这个神奇的家伙,废话不多说,开始介绍它的安装配置与使用. 1. 下载noNVC 好多渠道可以下载到noVNC,可以直接访问noVNC的官方网页ht ...

  9. Nginx启动和停止

    启动nginx [root@LinuxServer sbin]#  /usr/local/nginx/sbin/nginx     -c     /usr/local/nginx/conf/nginx ...

  10. Elasticsearch-C#操作

    初始化实例 nuget安装 1.单点连接 var node = new Uri("http://myserver:9200"); var settings = new Connec ...