推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zrp1994

JavaScript 里面使用 instanceof 来判断变量是否为 function,这种用法有什么问题么?看到用的不多。。。

  •  
  •   zrp1994 · Aug 21, 2015 · 5932 views
    This topic created in 3919 days ago, the information mentioned may be changed or developed.

    顺便查了下 instanceof 的原理。暂时没发现这样判断有什么问题……

    23 replies    2015-08-22 22:40:50 +08:00
    immjun
        1
    immjun  
       Aug 21, 2015
    typeof
    exoticknight
        2
    exoticknight  
       Aug 21, 2015
    我用 typeof
    zrp1994
        3
    zrp1994  
    OP
       Aug 21, 2015
    @immjun
    @exoticknight
    我知道有 typeof ,但是为什么大家不用 instanceof 呢? typeof 跨浏览器很多问题的
    learnshare
        4
    learnshare  
       Aug 21, 2015
    可以看看 underscore 或 lodash 的实现方式
    mcfog
        5
    mcfog  
       Aug 21, 2015   ❤️ 2
    zrp1994
        6
    zrp1994  
    OP
       Aug 21, 2015
    @mcfog 好吧……强行改变隐型原型……这个算一条
    mcfog
        7
    mcfog  
       Aug 21, 2015
    还有个反向的例子



    浏览器里不高兴找哪里有 util.inherits 了就用了 node
    wssgcg1213
        8
    wssgcg1213  
       Aug 21, 2015
    跨 context 比如 iframe
    YuJianrong
        9
    YuJianrong  
       Aug 21, 2015
    @zrp1994 typeof 跨浏览器有什么问题?

    另外改__proto__不算一条,这个根本不应该改,该出错了就错了呗。

    虽然我觉得两个都可以,不过语义上显然 typeof 更合理,虽然 function 确实也是对象,但 instanceof 语义上应该是确定普通对象的类型,而不是像这样用在确定 function 上,毕竟 function 已经被“虚拟”成一种高于对象的类型了(所以 typeof func === "function"),实在没办法的类型比如 Date 才应该用 instanceof 或者 Object.prototype.toString.call
    zrp1994
        10
    zrp1994  
    OP
       Aug 21, 2015
    @mcfog 我去看下 util.inherits
    zrp1994
        11
    zrp1994  
    OP
       Aug 21, 2015
    @YuJianrong 你再 IE 8 及以下试下 alert (window.open )
    spance
        12
    spance  
       Aug 21, 2015
    instanceof 判断左是不是右的一个实例,或者左是不是从右继承来的,判断依据是 左.__proto__===右.prototype
    typeof 检查变量的类型,等同于强类型语言的变量类型自举。
    明显,这 2 个语义是完全不同的。

    是一个 function 的实例,它未必是一个 function 类型。
    是一个 function 类型,它一定(默认)是从 Function 继承的。


    @mcfog 你的例子, MyFunction 是一个 constructor , b 是 MyFunction 的一个实例,这个 constructor 只是构造了一个普通的 object 就是 b 但它不是一个 function 类型,但却是从 MyFunction 分娩来的,所以 instanceof 一定是真。
    zrp1994
        13
    zrp1994  
    OP
       Aug 21, 2015
    @mcfog
    @spance
    是不是可以这么理解?
    MyFunction.prototype = Function;
    b = new MyFunction
    因为这时:
    b.__proto__.__proto__ === MyFunction.prototype === Function
    所以导致 instanceof 无法真实反映 b 的类型?
    spance
        14
    spance  
       Aug 21, 2015
    @zrp1994 instanceof 反应的结果哪里有问题?(如果没有修改__proto__等私有属性的话)

    b is a instance of MyFunction
    MyFunction extends from Function
    Function extends from Object

    所以, b instanceof MyFunction====true
    b instanceof Function====true
    b instanceof Object====true
    但是, b is not a Function
    spance
        15
    spance  
       Aug 21, 2015
    @zrp1994 sorry,b instanceof Function====false 因为 b.__proto__ ==== {} object
    而 Function.prototype=Function
    instanceof 判断依据是 左.__proto__===右.prototype 并且不断向上递推直到左的.__proto__是 null
    zrp1994
        16
    zrp1994  
    OP
       Aug 21, 2015
    @spance 明白了
    一般的函数字面量表示的函数它们已经是 Function 的实例了,他们的直接 prototype 指向的不是 Function ,在此基础上构造出的新实例的__proto__指向的也不是 Function ,所以 instanceof 不是 Function

    然而按照上面的修改,改变了 MyFunction 的 prototype 指向, instanceof 从功能上讲是准确的

    其实我的意思是 b 在这个时候从意义上讲更应该是一个 object ,而且 typeof b 也是“ object ”,我觉着这个时候用 instanceof 判断 b 的“类型”就不准确了
    YuJianrong
        17
    YuJianrong  
       Aug 21, 2015
    @zrp1994 没 IE8 及以下,不能直接说一下吗……

    完全看不懂后面你们在说啥了……

    MyFunction.prototype = Function;

    这个基本没有意义不大会有人这样做吧?毕竟 function 是特殊对象……
    spance
        18
    spance  
       Aug 21, 2015
    @zrp1994 是的,实际上对 instanceof 的判断就是要从左.__proto__===右.prototype 来是准确的。
    因为如果继承是用父构造方法 apply 的方式,此时 instance.__proto__是自己的构造方法的(这是被 new 设值的),不会等于父构造方法,也就是说 instance 除了 instaceof 自己构造方法是 true 就剩下 Object 是 true 了,中间继承链上的父、爷等不会 true.
    如果是用 prototype 方式继承的,那么父、爷的 prototype 被继承时人为修改了,在左.__proto__===右.prototype 的判断中是相等的,那么就会有不光是自己构造方法的 isinstanceof==true 还会有中间链上的 isinstanceof==true 了,此时 instanceof 的效果就类似于普通面向对象语言的 isinstanceof 的语义了。
    zrp1994
        19
    zrp1994  
    OP
       Aug 21, 2015
    @YuJianrong 低版本 IE 中 native functions 的 typeof 的结果不是“ function ”而是“ object ”
    YuJianrong
        20
    YuJianrong  
       Aug 21, 2015
    原来如此。不过 native function 本来就不大会用上 typeof 吧。
    scriptfans
        21
    scriptfans  
       Aug 21, 2015
    LancerComet
        22
    LancerComet  
       Aug 21, 2015
    好像 Object.prototype.toString.call () 很少有人使用
    an168bang521
        23
    an168bang521  
       Aug 22, 2015
    Object.prototype.toString.call ()是最完美的判断方法, instanceof 如果原型中修改了,就不准了; typeof 再检测 Object 的时候,正则,数组,日期,等所有的都是返回 Object ,不精确;
    上面的方法也可以用 Object 的实例来代替,比如[].toString.call ()
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3747 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 62ms · UTC 04:54 · PVG 12:54 · LAX 21:54 · JFK 00:54
    ♥ Do have faith in what you're doing.