JavaScript: problem with ActiveX object and apply () - function

I have an ActiveX object (Wizard) and you want to dynamically activate functions. For this, I use the apply () function. But unfortunately, InternetExplorer tells me something like: "This object does not support this method." Can someone give me a hint what can I do?

(To test this, you can also use a small flash object like Master and call "doSomething" instead of my specific "Initialize".)

function invoke(object, fnName, args)
{
  return object[fnName].apply(object, args);
}

function test_it()
{
  try{
    Master = window.document["Master"];
  }
  catch(e){alert(e);}
  var param = [1,"VC2"]; 
  var ret = invoke(Master, "Initialize", param);
  alert("got: "+ret);
}

For comparison, this is the apply () function in action:

function Obj()
{
  this.msg = function(a, b, c)
  {
      alert("msg: \n a: "+a+"\n b: "+b+"\n c: "+c);
      return "hi";
  }
    return this;
}


function invoke(object, fnName, args)
{
  return object[fnName].apply(object, args);
}

function test_it()
{
  var obj = new Obj();
  var ret = invoke(obj, "msg", [1, 2, 3]);
  alert("got: "+ret);
}
+3
source share
5 answers

kangax ! , ( ) -. , , , eval()!

function proxy(obj)
{
    this.obj = obj;

    this.Initialize = function(a, b)
    {
        return obj.Initialize(a, b);
    }   
}

function test_it()
{
    var myMaster = new proxy(window.document["Master"]);    
    var ret = myMaster["Initialize"].apply(myMaster, [1, "VC2"]);
    alert(ret);
}

, !

+1

( ) IE ( IE) , Function.prototype ( Object.prototype). , , , , . , Function.prototype, , instanceof; Function; Function.prototype.*, call apply. [[Class]] , "Function", ( , [[Class]] Object.prototype.toString).

, , , ( ECMA-262, 3- .). - , , (, hostObject.hostMethod()); , delete (, delete hostObject.hostMethod). , , - native Function.prototype.

( ) , .

call:)

"" IE- , [[Call]], call apply, .

apply , :

function f(){ return arguments };
Function.prototype.apply.call(f, null, [1,2,3]); // [1,2,3] 

null , , .

apply , call:

// should work in IE6, even though `alert` has no `call` there
Function.prototype.call.call(alert, window, 'test');

// Calls Master.initialize borrowing from Function.prototype
Function.prototype.apply.call(Master.initialize, Master, [1,"VC2"]);
+3

, , thunk , ( , , ActiveX ).

varArgsThunkFunctionsCache = [];

function getVarArgsThunkFunction(arrayLength) {
  var fn = varArgsThunkFunctionsCache[arrayLength];
  if (!fn) {
    var functionCode = 'return o[m](';
    for (var i = 0; i < arrayLength; ++i) {
      if (i != 0) {
        functionCode += ','
      }
      functionCode += 'a[' + i + ']';
    }
    functionCode += ')';
    fn = new Function('o', 'm', 'a', functionCode);
    varArgsThunkFunctionsCache[arrayLength] = fn;
  }
  return fn;
};


function invoke(object, methodName, args) {
  var fn = getVarArgsThunkFunction(args.length);
  return fn(object, methodName, args);
};
+2

, IE JS- ActiveX JavaScript-, apply(). , eval() - , .

function invoke(objectName, fnName, args) {
    return eval(objectName + "." + fnName + "(" + args + ")");
}
+1

Just thought that I would say that if you use the method eval, since Ates Goral said that you need to be careful with the string arguments in your array, since they will be considered variable names, for example

function invoke(objectName, fnName, args) {
    return eval(objectName + "." + fnName + "(" + args + ")");
}
invoke("Master", "Initialize", [1, "VC1"]);

eval a string will be passed

Master.Initialize(1,VC1)

which throws an error if VC1 is not a specific variable. It is best to "expand" the name of the array instead of passing literals:

function UnrollArray(arrayname, length) {
    var s = "";
    for(var i = 0; i < length; i++) {
        s += arrayname + "[" + i + "],";
    }
    return s.substring(0, s.length - 1); //remove the trailing comma
}

therefore invoke becomes

function invoke(objectName, fnName, args) {
    var unrolledarray = UnrollArray("args", args.length);
    return eval(objectName + "." + fnName + "(" + unrolledarray + ");");
}
invoke("Master", "Initialize", [1, "VC1"]);

eval will be transferred

Master.Initialize(args[0],args[1]);
0
source

Source: https://habr.com/ru/post/1717840/


All Articles