理解原型和原型链。需从构造函数、__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. 【Dart学习】--Dart之数字(num)相关方法总结

    一,部分属性 用法一(figureA) int figureA = -93; 是否为负数 print(figureA.isNegative); figureA是否是有限的 print(figureA. ...

  2. Spring5源码分析之启动类的相关接口和注解

    一些基础但是核心的知识总结: Spring Boot项目启动的时候需要加@Configuration. @ComponentScan @Configuration + @Bean 把第三方jar包注入 ...

  3. ES6深入浅出-8 新版的类(下集)-3.书籍推荐

  4. Hive Essential (4):DML-project,filter,join,union

    1. Project data with SELECT The most common use case for Hive is to query data in Hadoop. To achieve ...

  5. MySQL插入大批量数据时报错“The total number of locks exceeds the lock table size”的解决办法

    事情的原因是:我执行了一个load into语句的SQL将一个很大的文件导入到我的MySQL数据库中,执行了一段时间后报错"The total number of locks exceeds ...

  6. JavaScript图形实例:图形的扇形变换和环形变换

    1.1  扇形变换 将如图1所示的上边长方形的图形变换为下边的扇形图形的变换称为扇形变换. 设长方形图形中任一点P1(X1,Y1)变换为扇形图形上的点P2(X2,Y2),长方形的长为X,扇形圆心坐标为 ...

  7. 【转载】我为什么放弃了 Linux 内核学习?

    最近学习内核很是心累,碰巧看到这篇文章,有点意思~ 转自http://happypeter.github.io/index.html,以下为原文内容: 我在国内的技术类网站 / 博客上, 时常会看到分 ...

  8. va_start(),va_end()函数应用

    原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下. VA_LIST的用法:            (1)首先在函数里定义一具VA_LIST型的变 ...

  9. Linux下go环境搭建

    一:先从https://golang.google.cn/dl/下载,我这边下载的是go1.13.3.linux-amd64.tar.gz: 二:将压缩包解压后得到go目录,将go目录移动到/usr/ ...

  10. LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14

    108. 将有序数组转换为二叉搜索树 108. Convert Sorted Array to Binary Search Tree 题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索 ...