Prototype Chain
参考资料:
- 《javascript权威指南 第六版》
- 《javascript高级程序设计 第二版》
写在前面的话
所谓的原型链就是一个一个的对象通过其__proto__属性连接起来的数据结构
(链)。这个数据结构对JS的继承很重要。
object a object b object c
|----------| |---------| |---------|
|__proto__----> |__proto__---->|__proto__----> ...
|----------| |---------| |---------|
- js的世界里除了简单数据类型(Number,String,Boolean,Undefined,Null)就是复杂数据类型——对象,连作用域都是对象。
- 简单数据类型很简单,就是简单的数据段,直接赋值给变量,生存在栈中,因为它们的大小设置好后就不可以改变。
- 复杂数据类型很复杂,由多类型值组成,生存在堆中,栈中的变量只有对这个复杂数据类型的内存引用,设置好后可能会发生变化。
- 有些语言(java,c#)把字符串设置为对象,但是js放弃了。
- 每个对象都有一个__proto__属性,它默认指向另一个对象(构造这个对象的构造器的prototype属性指向的对象)或者为null(null是一个空对象,什么也没有,Object.prototype.__proto__===null),现代浏览器都支持你访问到这个属性。
- 当引擎读取一个对象的属性时,引擎先找自身的是否有个这个属性,没有的话按照自身的__proto__属性指向的对象查找,一直递归查询到Object.prototype指向的对象为止,因为Object.prototype.__proto__===null。
- 每个Function对象(包括Function自己)都有一个prototype属性,它指向一个对象,这个对象有一个constructor属性默认指向这个引用对象函数对象。
- js中的函数是一个对象,一个特殊的对象。
1 函数对象和对象
可以说函数对象是对象扩展,相比普通对象函数对象多了一个逻辑代码+prototype属性。prototype属性指向一个对象,这个对象有一个constructor属性指向函数对象。


2 new操作符
当我们使用new调用构造函数时会自动的创建一个对象,因此构造函数本身只要初始化这个新对象的状态。调用构造函数的一个特征就是把构造函数的prototype属性被用作新对象的原型,即新对象的__proto__属性会指向构造函数的prototype指向的对象。多个对象的__proto__都指向同一个prototype对象。
3 函数执行的本质
当我们调用一个函数时是这样的:查找函数对象中逻辑代码,执行之。
4 构造函数和函数
2个都是函数,只不过是调用的方式不同导致他们叫法不一样。当使用new操作符调用函数时函数叫构造器,使用(),apply,call时叫函数。
instanceof运算符的原理
A instanceof B
流程:先计算B.prototype,然后查询A.__proto__判断是否相同,不同则继续沿着A.__proto__.__proto__查找是否相同(也就是沿着原型链查找),直到原型链的头Object.prototype.__proto__。
5 Object,Function
Object是所有对象直接或者间接构造器,Function是所有函数的直接或者间接构造器,但是他们指向的对象都是函数对象。
5.1 谁是上帝
回想下instanceof的原理吧。
Function instanceof Function;
Function instanceof Object;
Object instanceof Function;
Object instanceof Object;

6 TEST
推测下alert出什么值?console出什么值?
Object.prototype.sth = "O";
Function.prototype.sth = "F";
function f() {
return function () {
console.log(this.sth);//F
return sth;
}
}
alert(f().apply(function(){}));//O
6.1 提示
- 作用域在js里也是对象,查找变量也是在作用域对象中查找的。
- typeof window === 'object'
6.2 解释变量的二维查找
alert的值:引擎先查找返回的匿名函数的作用域对象,发现没有sth变量,进而沿着作用域链的第二位查找f的作用域对象,发现也没有,接着查找globel(window)作用域对象,发现也没有。接着sth会在全局的global对象的属性来查找,沿着global对象的原型链查找,发现Object.prototype.sth = "O",所以...
console的值:这里的this是apply指定的执行环境:匿名函数。匿名函数的原型链上存在sth,所以输出F。
window.__proto__===Window.prototype;//true
Window.__proto__===Object.prototype;//true
window instanceof Window;//true
window instanceof Object;//true
7 原型链的优势
代码复用,构造出的对象节省内存空间。
8 深入delete操作符
delete可以删除对象的属性,它的操作数应该是一个属性访问表达式,它只能删除对象自身的属性,不能删除原型链上的属性。
注意
如果对象没有这个属性,或者操作数不是属性表达式,返回true
var a = {};
delete a.b;//true
a.b = 1;
console.info(a.b);//1
delete a.b;//true
console.info(a.b);//undefined
delete 1;//true
但是如果删除的是全局属性,则可以省略对全局对象的引用,直接删除
window.a = 1;
delete a;//true
console.info(typeof window.a);//undefined
当delete删除一些不可以删除的属性返回false,全局环境声明的变量、函数是无法删除的。
var a = 1;
function f(){};
console.info(window.a);//1
delete a;//false
delete f;//false
delete window.a;//false
delete window.f;//false
console.info(window.a);//1
console.info(window.f);//function f(){}
eval执行的代码中声明的变量,函数是可以删除的,控制台的代码是放在eval中执行的。
eval("var a=1;function f(){};"); console.info(a);//1
console.info(f);//function f(){} delete a;//true
delete f;//true console.info(typeof a);//undefined
console.info(typeof f);//undefined
8.1 test
delete document.getElementById//true
document.hasOwnProperty("getElementById");//false 表明getElementById不是document的属性。
document.__proto__==HTMLDocument.prototype;//HTMLDocument是document的构造函数
HTMLDocument.prototype.hasOwnProperty("getElementById");//getElementById也不是HTMLDocument.prototype属性。
HTMLDocument.prototype.__proto__===Document.prototype;//true
Document.prototype.hasOwnProperty("getElementById");//true
document.__proto__.__proto__===Document.prototype;//沿着原型链可以看到getElementById属性来自Document.prototype。
delete Document.prototype.getElementById;//无法删除这个属性。
Document.prototype.getElementById=null;//修改这个属性
document.getElementById("xx");//TypeError: Property 'getElementById' of object #<HTMLDocument> is not a function
Prototype Chain的更多相关文章
- 深入理解原型链(Prototype chain) __proto__
原型链(Prototype chain) 原型对象也是普通的对象,并且也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链(prototype chain). A prot ...
- [Javascript] Link to Other Objects through the JavaScript Prototype Chain
Objects have the ability to use data and methods that other objects contain, as long as it lives on ...
- (翻译) Inheritance and the prototype chain 继承和原型链
JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++) ...
- Inheritance and the prototype chain 继承和 原型 链
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain Inherita ...
- prototype chain & prototype & __proto__
prototype chain & prototype & proto prototype chain MDN https://developer.mozilla.org/en-US/ ...
- illustrating javascript prototype & prototype chain
illustrating javascript prototype & prototype chain 图解 js 原型和原型链 proto & prototype func; // ...
- js & object & prototype & __proto__ & prototype chain
js & object & prototype & proto & prototype chain constructor prototype === instance ...
- 全面了解 Javascript Prototype Chain 原型链
原型链可以说是Javascript的核心特征之一,当然也是难点之一.学过其它面向对象的编程语言后再学习Javascript多少会感到有些迷惑.虽然Javascript也可以说是面向对象的语言,但是其实 ...
- Only Link: Inheritance and the prototype chain
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_cha ...
随机推荐
- 01 mongodb 的特点
mongoDB 介绍(特点.优点.原理) 介绍:MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. 特点:高性能.易部署.易使用,存 ...
- PMD:Java源代码扫描器
PMD是一个开源代码分析器.可以查找常见编程缺陷,比如未使用的变量.空catch代码块.不必要的对象创建等.支持Java.JavaScript.PLSQL.Apache Velocity.XML.XS ...
- 工具类之Condition
再次看到Condition,第一感觉还是觉得它和Mutex的功能是一样的,没必要存在.心里这么想,其实自己也知道怎么可能多余呢?老老实实的再分析一下代码,这次一定要把理解出来的内容记下来!都怪平时写代 ...
- 【hiho一下】第一周 最长回文子串
题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...
- Coursera machine learning 第二周 编程作业 Linear Regression
必做: [*] warmUpExercise.m - Simple example function in Octave/MATLAB[*] plotData.m - Function to disp ...
- 一个关于运维人员做事的很好的case,拿出来和大家共勉
很久没有写KM了,最近lester这边在梳理CDB这边存在的问题,并推动那些问题解决措施的落地.无疑当前CDB存在比较多的问题,也有很多坑.需要我们运维和开发的同学多思考问题的根源和解决办法,并付诸实 ...
- proxool连接池 异常
这是第二次整理这个文章: 首先说明proxool连接池有两种配置方式: 第一种:采用jdbc.properties的方式 第二种:采用proxool.xml的配置方 后面在完善这两种配置方式(在上班哦 ...
- [Catalan数]1086 栈、3112 二叉树计数、3134 Circle
1086 栈 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 栈是计算机中 ...
- jmeter--基于http+json接口的功能测试
jmeter--基于http+json接口的功能测试 测试项目叫做smile_task,简称sm_task.这是一个基于nodejs超简单的todo list,sm_task没有任何UI界面(纯接口) ...
- 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现
一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...