彻底搞懂js原型与原型链
原生的原型链
function fn(){},fn 为 Function的一个实例,原型链为 null -> Object -> Function -> fn:
fn.__proto__ === Function.prototype
Function.prototype.__proto === Object.prototype
Object.prototype.__proto__ === null
原型链通过原型(prototype)链接,prototype 就是一个 只有(构造)函数才有的特殊的实例,包含了constructor指针(和__proto__,所有实例都有)
之后new出来的普通实例(非prototype)都包含这个prototype(引用名为__proto__):console.log(sonA) // {/* 其他属性 */ __proto__: Son.prototype}
举例来说,对于函数实例,所有函数实例.__proto__ === Function.prototype (通过这个能拿到Function上的通用属性,如bind函数)
甚至Function.__proto__ === Function.prototype, Object.__proto__ === Function.prototype
Function instanceof Object // true Function.__proto__.__proto__ === Object.prototype (优先是更具体的函数,然后才作为更抽象的对象,对象永远在原型链较上层)
Object instanceof Function // true Object.__proto__ = Function.prototype
原型链继承:
未继承时
console.log(Son.prototype) // { constructor: Son, __proto__: Object.prototype }
原型链继承了Father时,
console.log(Son.prototype) // { __proto__: Father.prototype }父类的一个实例, 通过new Father 或者 Object.create(Father.prototype)生成
需要手动赋予constructor:
Object.defineProperty(Son.prototype, "constructor", {
value: Son,
writable: false
});
console.log(Object.prototype)
{ __proto__: null }
原型链继承,本质就是修改函数的prototype,使其从指向Function变为指向父类;父类的对象刚好符合这个特性
巩固一下上面的知识点,请判断以下比较是否为真:
Object.prototype.__proto__ === null
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
fn.__proto___ === Function.prototype
Object.prototype === Function.prototype.__proto__
Object.prototype === fn.prototype.__proto__
Object.prototype.isPrototypeOf(fn)
Object.prototype.isPrototypeOf(fn.prototype)
Function.prototype === fn.__proto__;
Function.prototype.isPrototypeOf(fn)
Function.prototype.isPrototypeOf(fn.prototype) // false
答案:以上判断若未特殊说明,结果都为真
谈一下new
自定义原型链:基于原型链的继承
Father() {} -> Son() {]
继承的本质是,如何使Son的实例能访问到Father定义的属性
通过原型链,我们将Son的原型指向Father
Son原型链现在是指向的Function,Son.__proto__ === Function.prototype
我们希望Son.__proto__ === Father.prototype
按es5之前的规范,我们不能直接访问__proto__,那么只能修改prototype (ES5中用Object.getPrototypeOf函数获得一个对象的[[prototype]]。ES6中,使用Object.setPrototypeOf可以直接修改一个对象的[[prototype]])
我们知道 Father的实例的__proto__指向Father.prototype,那么Son.prototype等于Father的实例就可以
Son.prototype = new Father() 或者
Son.prototype = Object.create(Father.prototype)
这里有一个问题,prototype的constructor属性应该指向构造函数,而这种写法的constructor通过原型链会找到Father,所以需要定义一下constructor
Object.defineProperty(Son.prototype, "constructor", {
value: Son,
writable: false
});
顺便了解一下原型链查找顺序
优先查找对象的,对象上没有则通过__proto__找prototype,还没找到,就找prototype.__proto__, 也就是父类的prototype
比如
对象objA查找hasOwnProperty
objA -> Son.prototype -> Object.prototype -> Object.prototype.hasOwnProperty
函数funcA查找bind
funcA -> Function.prototype -> Function.prototype.bind
PS:对于 const fn = () => {} 这样的箭头函数,不属于原型链的范畴 可以参考 http://www.cnblogs.com/mengff/p/9656486.html
彻底搞懂js原型与原型链的更多相关文章
- 帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...
- 彻底搞懂 JS 中 this 机制
彻底搞懂 JS 中 this 机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 目录 this 是什么 this 的四种绑定规 ...
- 让你彻底搞懂JS中复杂运算符==
让你彻底搞懂JS中复杂运算符== 大家知道,==是JavaScript中比较复杂的一个运算符.它的运算规则奇怪,容易让人犯错,从而成为JavaScript中“最糟糕的特性”之一. 在仔细阅读了ECMA ...
- 一文搞懂 js 中的各种 for 循环的不同之处
一文搞懂 js 中的各种 for 循环的不同之处 See the Pen for...in vs for...of by xgqfrms (@xgqfrms) on CodePen. for &quo ...
- 一文读懂JS中的原型和原型链(图解)
讲原型的时候,我们应该先要记住以下几个要点,这几个要点是理解原型的关键: 1.所有的引用类型(数组.函数.对象)可以自由扩展属性(除null以外). 2.所有的引用类型都有一个’_ _ proto_ ...
- 彻底搞懂js __proto__ prototype constructor
在开始之前,必须要知道的是:对象具有__proto__.constructor(函数也是对象固也具有以上)属性,而函数独有prototype 在博客园看到一张图分析到位很彻底,这里共享: 刚开始看这图 ...
- 一张图搞懂 Javascript 中的原型链、prototype、__proto__的关系 转载加自己的总结
1. JavaScript内置对象 所谓的内置对象 指的是:JavaScript本身就自己有的对象 可以直接拿来就用.例如Array String 等等.JavaScript一共有12内置对象 ...
- Spirit带你彻底搞懂JS的6种继承方案
JavaScript中实现继承的6种方案 01-原型链的继承方案 function Person(){ this.name="czx"; } function Student(){ ...
- 通过一张简单的图,让你彻底地搞懂JS的==运算
大家知道,JavaScript中的==是一种比较复杂运算,它的运算规则很奇怪,很容易让人犯错,从而成为JavaScript中“最糟糕的特性”之一. 在仔细阅读ECMAScript规范的基础上,我画了一 ...
随机推荐
- Python格式化字符
%s 字符串 %d 有符号整数(十进制) %f 浮点数字(用小数点符号)
- nginx运用
1.nginx的 命令 start nginx 这样,nginx 服务就启动了.打开任务管理器,查看 nginx.exe 进程,有二个进程会显示,占用系统资源,那是相当的少.然后再打开浏览器,输入 h ...
- P3440 [POI2006]SZK-Schools(费用流)
P3440 [POI2006]SZK-Schools 每所学校$i$开一个点,$link(S,i,1,0)$ 每个编号$j$开一个点,$link(i,T,1,0)$ 蓝后学校向编号连边,$link(i ...
- windows eclipse直接访问远程linux hadoop开发环境配置(符合实际开发的做法)
CDH 5.x搭建请参考CentOS 7离线安装CDH 5.16.1完全指南(含各种错误处理). 如果使用的是cloudera quickstart vm,则只能在linux服务器中使用eclipse ...
- [C++ Primer Plus] 第9章、内存模型和名称空间(一)程序清单
程序清单9.9(静态存储连续性.无链接性) #include<iostream> using namespace std; ; void strcount(const char *str) ...
- 【Axure RP8.1】一款专业的快速原型设计工具
Axure RP是一款专业的快速原型设计工具.Axure(发音:Ack-sure),代表美国Axure公司:RP则是Rapid Prototyping(快速原型)的缩写.Axure RP是美国Axur ...
- linux 修改普通用户的 max user process
因为出现 fork: retry: No child processes 问题 , google了一下 , 大家说是要去修改 /etc/security/limits.conf 文件 , 然后我用r ...
- 理解R语言gdistance包下的transition函数
library(raster)library(gdistance)r <- raster(nrows=3, ncols=4, xmn=0, xmx=7, ymn=0, ymx=6, crs=&q ...
- leecode第五百五十七题(反转字符串中的单词 III)
class Solution { public: string reverseWords(string s) { string res; stack<char> sta; string:: ...
- 关于虹软人脸识别SDK的接入
背景: 虹软的人脸识别还是不错的,在官方注册一个账号,成为开发者,下载SDK的jar包,在开发者中心,找一个demo就可以开始做了,安装里边的逻辑,先看理解代码,然后就可以控制代码,完成自己想要的功能 ...