zoukankan      html  css  js  c++  java
  • 探讨instanceof实现原理,并用两种方法模拟实现 instanceof

    在开始之前先了解下js数据类型

    js基本数据类型:

    null undefined number boolean string

    js引用数据类型:

    function object array


    一说instanceof  就想到typeof ,这里也介绍下typeof:

    typeof是用来判断数据类型的,就一个参数 ,使用方式像这样: typeof  num,  就是判断num是什么类型

    typeof 一般只能返回如下几个结果:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"; 除了"object" 其他都好说。

    着重看这几个:

    typeof 不存在的变量 = “undefined”

    typeof 对象 = “object”

    typeof  null = "object" 

    typeof 数组 = “object”

    typeod 方法的实例(比如 new Array()) =“object”

    对象,数组 都是引用类型, 使用typeof 结果是 object类型,但是null 是基本数据类型,使用typeof结果也是 object,

    可以这么理解:null 是 不指向任何对象 的 空指针, 因为它是指向对象的,所以typeof 就是 object, 但是它又是空的,所以就属于基本数据类型。

    但是要想判断一个变量是不是数组, 或者对象, 这时候就需要instanceof了(判断是不是null,直接用  变量 === null 就行, null===null 结果是 true)


    现在说instanceof, 要想从根本上了解 instanceof 的奥秘,需要从两个方面着手:

    1 语言规范中是如何定义这个运算符的。

    2 JavaScript 原型继承机制。

    一 JavaScript instanceof 语言规范 (简化版) 的运算代码如下:

    function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
     var O = R.prototype;
     L = L.__proto__;
     while (true) { 
       if (L === null) 
         return false; 
       if (O === L)  // 这里重点:当 O 严格等于 L 时,返回 true 
         return true; 
       L = L.__proto__; 
     } 
    }

    规则简单来说就是 L的  __proto__  是不是强等于 R.prototype,不等于再找  L.__proto__ .__proto__  直到 __proto__ 为 null  

     

    二  JavaScript 原型链,看下图:

     对上图的说明:

      1.function Foo 就是一个方法,比如内置的 Array ,String ,或者自定义的方法;

      2.function Object 就是Object

      3.function Function 就是Function

           4.以上三个其实都是function 所以他们的_proto_ 都是Function.prototype

      5.记住 String, Array, Number, Object, Function这些其实都是 function

    结合语言规范跟js的原型链,接下来我们看实际例子

    常规的用法:

    function F(){}
    var a = new F()
    console.log(a instanceof F) // 输出 true

      function child(){}
      function father(){}
      child.prototype = new father() 
      var a = new child()
      console.log(a instanceof father) // 输出true

     更高级点的用法:

    console.log(Object instanceof Object);//true
    console.log(Function instanceof Function);//true
    console.log(Number instanceof Number);//false
    console.log(String instanceof String);//false
    console.log(Function instanceof Object);//true
    console.log(Foo instanceof Function);//true
    console.log(Foo instanceof Foo);//false

    大家可以在控制台输出,可以直观的看到每个步骤的输出,结合instanceof 的规范跟js原型链 加深理解。


    模拟实现instanceof

    对于用 typeof 就可以判断出来数据类型的这里就不处理,只处理 typeof 结果为 object ,并且不是 null 的。

    方法一: 直接使用instanceof的规则

    
    

    <!DOCTYPE html>
    <html>
    <head>
    <title></title>
    </head>
    <body>
    <script type="text/javascript">
    function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
    var O = R.prototype;
    L = L.__proto__;
    while (true) {
    if (L === null)
    return false;
    if (O === L) // 这里重点:当 O 严格等于 L 时,返回 true
    return true;
    L = L.__proto__;
    }
    }
    // 开始测试
    var a = []
    var b = {}

    
    

    function Foo(){}
    var c = new Foo()

    function child(){}
    function father(){}
    child.prototype = new father()
    var d = new child()

    
    

    console.log(instance_of(a, Array)) // true
    console.log(instance_of(b, Object)) // true
    console.log(instance_of(b, Array)) // false
    console.log(instance_of(a, Object)) // true
    console.log(instance_of(c, Foo)) // true
    console.log(instance_of(d, child)) // true
    console.log(instance_of(d, father)) // true
    </script>
    </body>
    </html>

     

    方法二:在方法一的基础上使用 constructor (此方法无法用于判断继承)

    <!DOCTYPE html>
    <html>
    <head>
    <title></title>
    </head>
    <body>
    <script type="text/javascript">
    function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
    var O = R;
    L = L.__proto__;
    while (true) {
    if (L === null)
    return false;
    if (O === L.constructor) // 这里重点:当 O 严格等于 L 时,返回 true
    return true;
    L = L.__proto__;
    }
    }
    // 开始测试
    var a = []
    var b = {}

    function Foo(){}
    var c = new Foo()

    function child(){}
    function father(){}
    child.prototype = new father()
    var d = new child()

    console.log(instance_of(a, Array)) // true
    console.log(instance_of(b, Object)) // true
    console.log(instance_of(b, Array)) // false
    console.log(instance_of(a, Object)) // true
    console.log(instance_of(c, Foo)) // true
    console.log(instance_of(d, child)) // false 这里就是无法用于判断继承的
    console.log(instance_of(d, father)) // true
    </script>
    </body>
    </html>

      

  • 相关阅读:
    解决PKIX:unable to find valid certification path to requested target 的问题
    Linux 上的常用文件传输方式介绍与比较
    用VNC远程图形化连接Linux桌面的配置方法
    红帽中出现”This system is not registered with RHN”的解决方案
    linux安装时出现your cpu does not support long mode的解决方法
    CentOS SSH配置
    es6扩展运算符及rest运算符总结
    es6解构赋值总结
    tortoisegit安装、clon、推送
    es6环境搭建
  • 原文地址:https://www.cnblogs.com/yalong/p/10534858.html
Copyright © 2011-2022 走看看