V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zrp1994
V2EX  ›  JavaScript

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

  •  
  •   zrp1994 · 2015-08-21 10:23:53 +08:00 · 5450 次点击
    这是一个创建于 3414 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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



    浏览器里不高兴找哪里有 util.inherits 了就用了 node
    wssgcg1213
        8
    wssgcg1213  
       2015-08-21 10:47:32 +08:00
    跨 context 比如 iframe
    YuJianrong
        9
    YuJianrong  
       2015-08-21 11:02:55 +08:00
    @zrp1994 typeof 跨浏览器有什么问题?

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

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

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


    @mcfog 你的例子, MyFunction 是一个 constructor , b 是 MyFunction 的一个实例,这个 constructor 只是构造了一个普通的 object 就是 b 但它不是一个 function 类型,但却是从 MyFunction 分娩来的,所以 instanceof 一定是真。
    zrp1994
        13
    zrp1994  
    OP
       2015-08-21 11:28:00 +08:00
    @mcfog
    @spance
    是不是可以这么理解?
    MyFunction.prototype = Function;
    b = new MyFunction
    因为这时:
    b.__proto__.__proto__ === MyFunction.prototype === Function
    所以导致 instanceof 无法真实反映 b 的类型?
    spance
        14
    spance  
       2015-08-21 11:37:32 +08:00
    @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  
       2015-08-21 11:44:19 +08:00
    @zrp1994 sorry,b instanceof Function====false 因为 b.__proto__ ==== {} object
    而 Function.prototype=Function
    instanceof 判断依据是 左.__proto__===右.prototype 并且不断向上递推直到左的.__proto__是 null
    zrp1994
        16
    zrp1994  
    OP
       2015-08-21 11:50:33 +08:00
    @spance 明白了
    一般的函数字面量表示的函数它们已经是 Function 的实例了,他们的直接 prototype 指向的不是 Function ,在此基础上构造出的新实例的__proto__指向的也不是 Function ,所以 instanceof 不是 Function

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

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

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

    MyFunction.prototype = Function;

    这个基本没有意义不大会有人这样做吧?毕竟 function 是特殊对象……
    spance
        18
    spance  
       2015-08-21 12:17:30 +08:00
    @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
       2015-08-21 12:24:01 +08:00
    @YuJianrong 低版本 IE 中 native functions 的 typeof 的结果不是“ function ”而是“ object ”
    YuJianrong
        20
    YuJianrong  
       2015-08-21 12:35:57 +08:00
    原来如此。不过 native function 本来就不大会用上 typeof 吧。
    scriptfans
        21
    scriptfans  
       2015-08-21 13:02:05 +08:00
    LancerComet
        22
    LancerComet  
       2015-08-21 13:10:40 +08:00
    好像 Object.prototype.toString.call () 很少有人使用
    an168bang521
        23
    an168bang521  
       2015-08-22 22:40:50 +08:00
    Object.prototype.toString.call ()是最完美的判断方法, instanceof 如果原型中修改了,就不准了; typeof 再检测 Object 的时候,正则,数组,日期,等所有的都是返回 Object ,不精确;
    上面的方法也可以用 Object 的实例来代替,比如[].toString.call ()
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3035 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 14:27 · PVG 22:27 · LAX 06:27 · JFK 09:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.