关于javascript:如何获得最具体的X,使得y instanceof X为真?

How to get most specific X such that y instanceof X is true?

本问题已经有最佳答案,请猛点这里访问。

给定某个对象y,如何找出最具体的X,使表达式

1
y instanceof X

true进行评估?

例如,以下两个表达式的值都为true

1
2
[] instanceof Object
[] instanceof Array

…但是ArrayObject更具体。


按MDN:

The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor.

所以Kolink是正确的,检查y.constructor会得到你的答案。(注意,这假设您或其他人同时没有损坏y.constructor,即y__proto__(原型链的起点)实际上指向y.constructor.prototype


这是我刚写的一个代码,可以完成这项工作。阅读评论了解更多详细信息!

注意:我在Google Chrome下测试了这个代码片段!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
function compareTypes(a,b){
    if (a instanceof b) {
        if(b instanceof a) {
            /* same types */
            return 0;
        }
        else {
            /* first is son */
            return -1;
        }
    }
    if (b instanceof a) {
        /* second is son */
        return 1;
    }
    return 0; /* not related to each other */
}

function closestInstanceOf(obj, possibleTypesAsAdditionalArguments) {
    /*
    * How to call this function:
    * The first argument should be the object to check.
    * All other arguments are possible types.
    */


    if (arguments.length === 0)
        return; /* undefined */

    if (arguments.length === 1)
        return Object; /* If no possible type was passed, we returned Object as the base type */

    /* converts the arguments to Javascript array */
    var types = Array.prototype.slice.call(arguments, 0);

    var obj = types[0]; /* object to be checked */
    types.splice(0, 1); /* possible types */

    /* Sorts the types array from the more specific to the more generic type */
    types.sort(compareTypes);

    /* find the first match */
    for (var i = 0; i < types.length; i++) {
        var type = types[i];
        if (obj instanceof type) {
            return type;
        }
    }
    return Object;
}

// examples

// 1. Sorting types
console.info([Array, Number, Object, String, Boolean].sort(compareTypes));
// results:
//[function, function, function, function, function]
//  0: function Array() { [native code] }
//  1: function Number() { [native code] }
//  2: function String() { [native code] }
//  3: function Boolean() { [native code] }
//  4: function Object() { [native code] }

// 2. Find specific type
console.info(closestInstanceOf([], Array, Number, Object, String, Boolean));
// results:
// function Array() { [native code] }

// 3. Find specific type
console.info(closestInstanceOf(new String("Hello World"), Array, Number, Object, String, Boolean));
// results:
// function String() { [native code] }

// 4. Find specific type
console.info(closestInstanceOf(new Number(19), Array, Number, Object, String, Boolean));
// results:
// function Number() { [native code] }

// 5. Find specific type
console.info(closestInstanceOf("Hello world", Array, Number, Object, String, Boolean));
// results:
// function Object() { [native code] }
// Note: String iterals derived from object!

// 6. Find specific type
console.info(closestInstanceOf(18, Array, Number, Object, String, Boolean));
// results:
// function Object() { [native code] }
// The same applies for numbers

// 7. Find specific type
console.info(closestInstanceOf(false, Array, Number, Object, String, Boolean));
// results:
// function Object() { [native code] }
// And booleans...

// 8. Find specific type
console.info(closestInstanceOf(new Boolean(false), Array, Number, Object, String, Boolean));
// results:
// function Object() { [native code] }
// Again, using new Boolean does the job!


// 9. Find specific type
console.info(closestInstanceOf(function () { /* this is custom class */ }, Array, Number, Object, String, Boolean));
// results:
// function Object() { [native code] }
// This code works for custom class as well, try it!