Javascript 知识点:继承与原型链

Javascript 知识点:继承与原型链

  • 继承与原型链
  • 继承与原型链关系图
  • 验证关系图
    • 验证:实例对象
    • 验证:构造器
    • 验证:原型对象
  • 伪属性 __ proto __ 与 prototype 的关系
    • prototype
    • __ proto __
  • 由上文推出以下关系
    • 构造函数
    • 原型链 `__proto__与Function.prototype`
    • 原型对象
  • instanceof 谜题
  • 真●空对象
  • 参考资料

继承与原型链

顺手官网
JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
整篇文章写完之后,发现内容太多。总节以下几点。详情爱看不看23333333

  1. JS继承基础规则:所有函数默认都有一个属性prototype初始包含:constructor__proto__
  2. JS继承基础规则:所有对象都有属性__proto__用于指向创建它的那个构造函数的prototype
  3. JS继承基础规则:所有对象都有constructor属性,指向创建它的构造函数
  4. JS继承基础规则Object.prototype.__proto__指向null表示原型链到头了
  5. JS废话唠叨一下:万物皆是对象,函数也只是个添加了相关能力的对象
  6. JS废话唠叨一下:大多函数都可以当作构造函数。因此首字母大写,能方便我们辨认普通函数构造函数
    6.1 只能说大多数而不是全部,毕竟es6新加入的Symbol就不支持"new Symbol()"
  7. JS废话唠叨一下:所有函数都是Function创建的,因此:
    7.1. 所有函数的constructor都指向Function,连ObjectFunction自己也不例外
    7.2. 所有函数对象的__proto__都指向Function.prototype,连ObjectFunction自己也不例外

继承与原型链关系图

虽然网上有很多版本的关系图,但我还是自己画一个。
先说明一下一般的函数如 function MyMethod(){}; Array,Number,String... 这些都属于 Fn 级别。FunctionObject两个构造器辈份太大属于特殊情况。
Javascript 知识点:继承与原型链_第1张图片

验证关系图

验证:实例对象

var fn = new Array(1,2,3,4);
console.info(fn.constructor === Array);// true
console.info(fn.__proto__ === Array.prototype);// true

var obj = {};
console.info(obj.constructor === Object);// true
console.info(obj.__proto__ === Object.prototype);// true

验证:构造器

一个实例对象通过它的 __proto__ 属性指向它爹的 prototype 属性。

// 这里我直接用内置对象 Array 其实用自己声明的函数也一样。 Array 虽然是数组类型,但它首先也是 Function 的一个实例
// Fn
console.info(Array.constructor === Function);// true
console.info(Array.__proto__ === Function.prototype);// true
console.info(Array.hasOwnProperty('prototype'));// true

// Function
console.info(Function.constructor === Function);// true Function的构造函数只能是它自己。构造函数的祖宗就在这了。
console.info(Function.__proto__ === Function.prototype);// true 
console.info(Function.hasOwnProperty('prototype'));// true

// Object
console.info(Object.constructor === Function);// true
console.info(Object.__proto__ === Function.prototype);// true
console.info(Object.hasOwnProperty('prototype'));// true

验证:原型对象

// Fn.prototype
console.info(Array.prototype.constructor === Array);// true
console.info(Array.prototype.__proto__ === Object.prototype);// true

// Function.prototype
console.info(Function.prototype.constructor === Function);// true
console.info(Function.prototype.__proto__ === Object.prototype);// true

// Object.prototype
console.info(Object.prototype.constructor === Object);// true
console.info(Object.prototype.__proto__ === null);// true

伪属性 __ proto __ 与 prototype 的关系

__proto__ 指向 爹.prototype 下面详细的聊聊

prototype

  • 构造器上都有一个prototype属性
  • 想被继承的东西都放到 prototype
  • 想继承谁,就让你的.prototype.__proto__ 指向谁的 .prototype
// 首字母大写潜规则。表示这个函数是想当构造函数用的。
function Test(){};
Test.prototype.hehe = function(){ 
	console.info("呵呵!"); 
}

function Test2(){};
Test2.prototype = new Test();

// 创建实例
var test2 = new Test2();
test2.hehe();// 呵呵!

执行test2.hehe()时,首先在test2下找,肯定是没的。那么就它就继续顺藤__proto__摸瓜Test.prototypeTest.prototype中找到了hehe就执行,没找到就再往上,一直找到 Object.prototype 去。

  • 用官方的话说就是
    当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的( __proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

__ proto __

  • 它是对象的一个属性(官网的叫法:非标准的伪属性)
  • 它指向父类(创建此实例的构造函数)的prototype属性(这是创建对象时由系统完成的)
  • 它是各大浏览器厂商自发起来的。标准推荐使用 Object.getPrototypeOf(test2) 代替 test2.__proto__
Object.getPrototypeOf(test2) === test2.__proto__; // true
test2.__proto__ === Test2.prototype;// true

由上文推出以下关系

构造函数

可见所有函数都是由 Function 构造函数创建的。

console.info(Function.constructor === Function.prototype.constructor);// true
console.info(Object.constructor === Function.prototype.constructor);// true
console.info(Array.constructor === Function.prototype.constructor);// true
console.info(String.constructor === Function.prototype.constructor);// true

所有实例对象的constructor指向创建它的构造函数。

function MyMethod(){};
var myfn = new MyMethod();
console.info(myfn.constructor === myfn.__proto__.constructor);// true

所有构造函数的.prototype.constructor指向函数自己

function MyMethod(){};
console.info(MyMethod.prototype.constructor === MyMethod);// true
console.info(Array.prototype.constructor === Array);// true
console.info(String.prototype.constructor === String);// true
console.info(Function.prototype.constructor === Function);// true
console.info(Object.prototype.constructor === Object);// true

原型链 __proto__与Function.prototype

function MyMethod(){};
console.info(MyMethod.__proto__ === Function.prototype);// true
console.info(Array.__proto__ === Function.prototype);// true
console.info(String.__proto__ === Function.prototype);// true
console.info(Number.__proto__ === Function.prototype);// true
console.info(Set.__proto__ === Function.prototype);// true
// 不用我把所有js内置对象都列出来了吧。。。

原型对象

  • 据说Function.prototype 是一个特殊的匿名函数ƒ(){ [native code] }此函数的__proto__指向Object.prototype

  • 又有人说 JavaScript 直接规定的 Function.prototype.__proto__ === Object.prototype (反正结果一样)

  • Object.prototype.__proto__指向 null表明到达原型链末端。

// Function
Function.prototype;// ƒ () { [native code] }
Function.prototype.__proto__ === Object.prototype;// true

// Object
Object.prototype.__proto__ === null;// true

function MyMethod(){};
console.info(MyMethod.prototype.__proto__ === Object.prototype);// true
console.info(Array.prototype.__proto__ === Object.prototype);// true
console.info(String.prototype.__proto__ === Object.prototype);// true
console.info(Number.prototype.__proto__ === Object.prototype);// true
console.info(Set.prototype.__proto__ === Object.prototype);// true

instanceof 谜题

Function instanceof Object;//true
Object instanceof Function;//true

instanceof 运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。先看语法:

// object : 要检测的对象 
// constructor : 某个构造函数
object instanceof constructor

instanceof 的原理就是一级一级的向上检查 object.__proto__.__proto__ 是否等于 constructor.prototype
明白了instanceof原理,加上前面的 原型链关系图,相信这个结果就不难理解了吧。

真●空对象

var nullObje = Object.create(null);// 这家伙什么属性都没有。好干净
nullObje instanceof Object;// false
Object.getPrototypeOf(nullObje);//null

参考资料

  1. 基于原型链的继承 https://developer.mozilla.org/…

Javascript 知识点:继承与原型链_第2张图片

你可能感兴趣的:(Javascript)