简体   繁体   English

GWT中的Javascript instanceof&typeof(JSNI)

[英]Javascript instanceof & typeof in GWT (JSNI)

I've encountered an curious problem while trying to use some objects through JSNI in GWT. 我在GWT中尝试通过JSNI使用一些对象时遇到了一个奇怪的问题。 Let's say we have javscript file with the function defined: 假设我们有定义函数的javscript文件:

test.js: test.js:

function test(arg){
  var type = typeof(arg);
  if (arg instanceof Array)
    alert('Array');
  if (arg instanceof Object)
    alert('Object');
  if (arg instanceof String)
    alert('String');
}

And the we want to call this function user JSNI: 而我们想要调用这个函数用户JSNI:

public static native void testx()/ *-{
  $wnd.test( new Array(1, 2, 3) );
  $wnd.test( [ 1, 2, 3 ] );
  $wnd.test( {val:1} );
  $wnd.test( new String("Some text") );
}-*/;

The questions are: 问题是:

  • why instanceof instructions will always return false ? 为什么instanceof指令总是返回false
  • why typeof will always return "object" ? 为什么typeof将永远返回"object"
  • how to pass these objects so that they were recognized properly? 如何传递这些对象以便正确识别它们?

instanceof shouldn't be returning false all the time in your example unless you're testing objects from a different window, because an array from one window is not an instance of the Array constructor of a different window. instanceof不应该,除非你从不同的窗口测试对象,因为从一个窗口的数组不是实例在你的例子返回false,所有的时间Array不同的窗口的构造函数。

Using instanceof is great when you need to test for a specific thing and you're operating within one window (you do have to be aware of the string primitive vs. String object thing that scunliffe pointed out). 当你需要测试一个特定的东西并且你在一个窗口内操作时,使用instanceof很棒(你必须要知道scunliffe指出的字符串原语与String对象的东西)。 Note that you need to be careful of your order, since an array is an instanceof Object (as well as Array ); 请注意,您需要注意您的订单,因为数组是Objectinstanceof (以及Array ); this applies to String s and all other objects as well. 这适用于String s和所有其他对象。

There's an alternative that doesn't have the window issue and which can readily be used for switch statements and the like if you're doing dispatch: 有一个替代方案没有窗口问题,并且如果你正在进行调度,它可以很容易地用于switch语句等:

function classify(arg) {
    return Object.prototype.toString.call(arg);
}

That looks odd, but what it does is use the toString function on the Object prototype, which has a defined behavior (rather than using any override that the actual object you're testing may have, which may have different behavior). 这看起来很奇怪,但它的作用是使用Object原型上的toString函数,它具有已定义的行为(而不是使用您正在测试的实际对象可能具有的任何覆盖,这可能具有不同的行为)。 So given this function: 所以给定这个功能:

function show(arg) {
    alert(classify(arg));
}

you'll get these results: 你会得到这些结果:

show({});               // [object Object]
show("a");              // [object String]
show(new String("a"));  // [object String]
show([]);               // [object Array]
show(/n/);              // [object RegExp]
show(function() { });   // [object Function]

and you'll get those results regardless of what window the object you're testing is coming from and regardless of whether you use a string primitive or a String instance. 并且无论您使用字符串原语还是String实例,无论您正在测试的对象来自哪个窗口,您都将获得这些结果。

Since everything else seem to have been answered let me get this one: 由于其他一切似乎都得到了回答,让我得到这个:

how to pass these objects so that they were recognized properly? 如何传递这些对象以便正确识别它们?

GWT does this automagically for primitive types like Strings, Integers, etc. So you can write just: GWT会自动为字符串,整数等原始类型执行此操作。因此,您只需编写:

public static native String test1()/ *-{
   return "adfasdf";
}-*/;

public static native int test2()/ *-{
   return 23;
}-*/;

See the docs for some extra notes. 有关其他注释,请参阅文档

For arrays, there are a bunch of wrapper classes: JsArray , JsArrayBoolean , JsArrayInteger , JsArrayNumber , JsArrayString . 对于数组,有一堆包装类: JsArrayJsArrayBooleanJsArrayIntegerJsArrayNumberJsArrayString

public static native JsArrayString test3()/ *-{
   return ['foo', 'bar', 'baz'];
}-*/;

your test function always returns false because you do not supply a return statement... and String is funny in JavaScript... if you use new String("asdf"); 你的测试函数总是返回false,因为你没有提供一个return语句......并且String在JavaScript中很有趣......如果你使用new String("asdf"); then using instanceof will work, if you just create a string with "asdf" then you will need to use typeof. 然后使用instanceof将工作,如果你只是用"asdf"创建一个字符串,那么你将需要使用typeof。

function test(arg){
  if (arg instanceof Array){
    return 'Array';
  } else if(arg instanceof String || typeof(arg) == 'String'){
    return 'String';
  } else if (arg instanceof Object){
    return 'Object';
  } else {
    return typeof(arg);
  }
}

(note there are other types... Date, Number, Custom Objects etc.) (注意还有其他类型......日期,数字,自定义对象等)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM