理解原型和原型链。需从构造函数、__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. 将C++资源文件读取出来

    HRSRC   hResource   =   FindResource(GetModuleHandle(NULL),     MAKEINTRESOURCE(IDR_CALC),   TEXT(&q ...

  2. easyUIDataGrid对象返回值

    import java.util.List; /** * easyUIDataGrid对象返回值 * <p>Title: EasyUIResult</p> * <p> ...

  3. 基于grafana+prometheus构建Flink监控

    先上一个架构图 Flink App : 通过report 将数据发出去 Pushgateway :  Prometheus 生态中一个重要工具 Prometheus :  一套开源的系统监控报警框架 ...

  4. LabWindows/CVI入门之第四章:库文件(转)

    按语: 在参考CVI参考书使用CVI生成动态库后,在另一工程中调用DLL ,编译通不过,后参考此文,豁然开朗. http://blog.sina.com.cn/s/blog_6373e9e60101b ...

  5. 【2B设计】途牛商旅全案设计

    整体设计方案: 途牛商旅全案设计 https://www.uisdc.com/tuniu-business-travel

  6. 【JS新手教程】JS获取当前星期几的几种方法

    该文通过获取星期几的几种方法,介绍JS里的数组,判断,和字符串截取,可以当作新手教程看,小白也看的懂.获取星期几,可通过Date()对象的getDay()获取,获取的是一个数字,对应的是0,1,2,3 ...

  7. SQL Server判断对象是否存在

    1 判断数据库是否存在 if exists (select * from sys.databases where name = ’数据库名’) drop database [数据库名] if exis ...

  8. 微软3389远程漏洞CVE-2019-0708批量检测工具

    0x001 Win下检测 https://github.com/robertdavidgraham/rdpscan C:\Users\K8team\Desktop\rdpscan-master\vs1 ...

  9. Visual Studio 2019 社区版本离线安装

    官方指导 :https://docs.microsoft.com/en-us/visualstudio/install/create-an-offline-installation-of-visual ...

  10. List<E>

    List<E>——列表 有序,存储和读取的顺序是一致的 由整数索引 允许重复 add(int index,E element)——将元素插入指定位置 get(int index)——获取指 ...