参考资料:

  • 《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的更多相关文章

  1. 深入理解原型链(Prototype chain) __proto__

    原型链(Prototype chain) 原型对象也是普通的对象,并且也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链(prototype chain). A prot ...

  2. [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 ...

  3. (翻译) Inheritance and the prototype chain 继承和原型链

    JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++) ...

  4. Inheritance and the prototype chain 继承和 原型 链

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain Inherita ...

  5. prototype chain & prototype & __proto__

    prototype chain & prototype & proto prototype chain MDN https://developer.mozilla.org/en-US/ ...

  6. illustrating javascript prototype & prototype chain

    illustrating javascript prototype & prototype chain 图解 js 原型和原型链 proto & prototype func; // ...

  7. js & object & prototype & __proto__ & prototype chain

    js & object & prototype & proto & prototype chain constructor prototype === instance ...

  8. 全面了解 Javascript Prototype Chain 原型链

    原型链可以说是Javascript的核心特征之一,当然也是难点之一.学过其它面向对象的编程语言后再学习Javascript多少会感到有些迷惑.虽然Javascript也可以说是面向对象的语言,但是其实 ...

  9. Only Link: Inheritance and the prototype chain

    Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_cha ...

随机推荐

  1. 利用freemarker生成带fusioncharts图片的word简报

    /**  * 利用freemarker生成带fusioncharts图片的word简报  *         烟台海颐软件技术论坛  *         作者  牟云飞 新建 *         毕业 ...

  2. billboard因为合批导致出问题的一个想法

    由于unity中距离较近的2个billboard物体会动态合批,如果缩放不同,显示就有问题.还得在shader中"DisableBatching"="true" ...

  3. PHP-Manual的学习----【语言参考】----【类型】-----【Resource 资源类型】

    2017年8月24日11:29:361.资源 resource 是一种特殊变量,保存了到外部资源的一个引用.资源是通过专门的函数来建立和使用的.2.由于资源类型变量保存有为打开文件.数据库连接.图形画 ...

  4. MapReduce Input Split(输入分/切片)具体解释

    看了非常多博客.感觉没有一个说的非常清楚,所以我来整理一下. 先看一下这个图 输入分片(Input Split):在进行map计算之前,mapreduce会依据输入文件计算输入分片(input spl ...

  5. jQuery.callbacks 注释

    (function( jQuery ) { // String to Object flags format cache var flagsCache = {}; // Convert String- ...

  6. ASP连接数据库SQLServer

    Set conn=Server.CreateObject("adodb.connection")Set conn1=Server.CreateObject("adodb. ...

  7. 20179209《Linux内核原理与分析》第十二周作

    缓冲区溢出漏洞实验 缓冲区溢出简介 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器 ...

  8. 在函数中如何获取 线程对象、线程唯一ID

    threading.current_thread() threading.current_thread().ident

  9. Intel Quick Sync Video Encoder 2

    这边博客主要记录在预研quick sync中涉及到的一些性能质量相关的关键参数设置. github: https://github.com/MarkRepo/qsve 1. VPP处理过程伪代码: M ...

  10. 小程序 requestAnimationFrame 死循环

    小程序没有requestAnimationFrame  这个方法,小游戏有,使用这个方法会造成死循环