Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

你真的了解 instanceof 吗? #36

Open
amandakelake opened this issue Mar 25, 2018 · 0 comments
Open

你真的了解 instanceof 吗? #36

amandakelake opened this issue Mar 25, 2018 · 0 comments

Comments

@amandakelake
Copy link
Owner

amandakelake commented Mar 25, 2018

通常解释

在JS中,用typeof来判断基本类型,instanceof判断引用类型
这是大家通常的解释

但是,你真的了解instanceof吗?

例子

先看几个例子热一下身

console.log('aa' instanceof String) // 都说了判断引用类型,拿个基本类型出来坑爹么
let obj_string = new String('aa');
console.log(obj_string instanceof String)
// 大家伙们都属于object
console.log({} instanceof Object)
console.log([] instanceof Array)
console.log([] instanceof Object)
console.log(function() {} instanceof Function)
console.log(function() {} instanceof Object)
function Foo(){} 
function BFoo(){} 
Foo.prototype = new BFoo();//JavaScript 原型继承
let foo = new Foo();
console.log(foo instanceof Foo);
console.log(foo instanceof BFoo);

其实上面三个例子都比较基础,相信都难不倒大家,再看几个复杂点的

console.log(String instanceof String); 
console.log(Object instanceof Object); 
console.log(Function instanceof Function); 
console.log(Function instanceof Object);

function Foo(){} 
function BFoo(){} 
Foo.prototype = new BFoo();
console.log(Foo instanceof Function);
console.log(Foo instanceof Foo);

打印看看,你全答对了吗?
是的话就不用看下去了,大神请回吧;
如果不是,那可以往下翻一翻

MDN的定义

instanceof - JavaScript | MDN

object instanceof constructor

instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

先看MDN里面的解释,左边是要测试的对象,右边是构造函数
是否能在对象的原型链上(顺着__proto__一直往上找)找到构造函数的原型属性([constructor].prototype)

直接看实现代码吧

function instance_of(L, R) {//L 表示左边的object,R 表示右边的constructor
 const R_P = R.prototype;// 取 R 的显式原型
 L = L.__proto__;// 取 L 的隐式原型,并且可能会顺着原型链重新赋值
 while (true) { 
   if (L === null) 
     return false; 
   if (R_P === L)// 这里重点:严格比较 true 
     return true; 
   L = L.__proto__; 
 } 
}

再祭出我们的原型链大杀器
image

划个重点

  1. __proto__ 属性,指向了创建该对象的构造函数的原型
  2. 所有JS 对象都有 __proto__ 属性,除了Object.prototype.__proto__ === null
  3. 注意Object(),它是由function生成的,所以它的__proto__属性指向了function的构造器Function的原型Function.prototype
  4. 注意构造器Function,它是唯一一个prototype__proto__指向相同的对象
  5. 一般来说,我们日常自行创建的构造器Foo__proto__属性指向function的构造器Function的原型Function.prototype,但是构造器的原型对象Foo.prototype__proto__属性是直接指向Object.prototype对象的

例子讲解:彻底捋清instanceof

直接找一个例子来讲解,相信聪明的你们一定能够融会贯通,举一反三

console.log(Object instanceof Object); // true

再看instanceof的实现代码

function instance_of(L, R) {//L 表示左边的object,R 表示右边的constructor
 const R_P = R.prototype;// 取 R 的显式原型
 L = L.__proto__;// 取 L 的隐式原型,并且可能会顺着原型链重新赋值
 while (true) { 
   if (L === null) 
     return false; 
   if (R_P === L)// 这里重点:严格比较 true 
     return true; 
   L = L.__proto__; 
 } 
}

1、第一轮赋值

首先,左右表达式赋值

L = Object
R = Object
R_P = Object.prototype = Object.prototype
L = Object.__proto__ = Function.prototype

2、第一次判断

L !== null => R_P !== L
判断不为true
继续寻找L的原型链,准备下一轮赋值

3、第二轮赋值

L = Function.prototype.__proto__  =  Object.prototype

4、第二次判断

L !== null => R_P === L

return true

完美结束!

好了,其他的例子,请同学们自己去分析吧,你现在可以出去跟别人说:我真滴了解instanceof!

后记

感谢您耐心看到这里,希望有所收获!

如果不是很忙的话,麻烦右上角点个star⭐,举手之劳,却是对作者莫大的鼓励。

我在学习过程中喜欢做记录,分享的是自己在前端之路上的一些积累和思考,希望能跟大家一起交流与进步,更多文章请看【amandakelake的Github博客】

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant