参考资料:

  • 《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. 01 mongodb 的特点

    mongoDB 介绍(特点.优点.原理) 介绍:MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. 特点:高性能.易部署.易使用,存 ...

  2. PMD:Java源代码扫描器

    PMD是一个开源代码分析器.可以查找常见编程缺陷,比如未使用的变量.空catch代码块.不必要的对象创建等.支持Java.JavaScript.PLSQL.Apache Velocity.XML.XS ...

  3. 工具类之Condition

    再次看到Condition,第一感觉还是觉得它和Mutex的功能是一样的,没必要存在.心里这么想,其实自己也知道怎么可能多余呢?老老实实的再分析一下代码,这次一定要把理解出来的内容记下来!都怪平时写代 ...

  4. 【hiho一下】第一周 最长回文子串

    题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...

  5. Coursera machine learning 第二周 编程作业 Linear Regression

    必做: [*] warmUpExercise.m - Simple example function in Octave/MATLAB[*] plotData.m - Function to disp ...

  6. 一个关于运维人员做事的很好的case,拿出来和大家共勉

    很久没有写KM了,最近lester这边在梳理CDB这边存在的问题,并推动那些问题解决措施的落地.无疑当前CDB存在比较多的问题,也有很多坑.需要我们运维和开发的同学多思考问题的根源和解决办法,并付诸实 ...

  7. proxool连接池 异常

    这是第二次整理这个文章: 首先说明proxool连接池有两种配置方式: 第一种:采用jdbc.properties的方式 第二种:采用proxool.xml的配置方 后面在完善这两种配置方式(在上班哦 ...

  8. [Catalan数]1086 栈、3112 二叉树计数、3134 Circle

    1086 栈 2003年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 栈是计算机中 ...

  9. jmeter--基于http+json接口的功能测试

    jmeter--基于http+json接口的功能测试 测试项目叫做smile_task,简称sm_task.这是一个基于nodejs超简单的todo list,sm_task没有任何UI界面(纯接口) ...

  10. 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现

    一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...