문제

ActiveX 객체 (마스터)가 있으며 함수를 동적으로 호출하고 싶습니다. 이를 위해 apply () 함수를 사용합니다. 그러나 슬프게도 InternetexPlorer는 "이 개체는이 방법을 지원하지 않습니다"라는 줄을 따라 무언가를 말해줍니다. 누군가 내가 할 수있는 일을 힌트를 줄 수 있습니까?

(이것을 테스트하기 위해 작은 플래시 객체를 마스터로 사용하고 특정 "초기화"대신 "dosomething"을 호출 할 수도 있습니다.)

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);
}

Comparsion의 경우, 이것은 Apply () 함수가 작동합니다.

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);
}
도움이 되었습니까?

해결책 4

시간과 광범위한 설명에 대해 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);
}

다시 한번, 시간 내 주셔서 감사합니다!

다른 팁

IE (IE뿐만 아니라)의 일부 호스트 객체 (즉, 네이티브 객체)의 문제는 그들이 상속하지 않는다는 것입니다. Function.prototype (그리고 종종 최상위 레벨도 아닙니다 Object.prototype). 일부 호스트는이를 반대합니다 기능처럼 보일 수 있습니다 실제로 부름을받을 수 있다는 것을 제외하고는 기능과 관련이 없습니다. 이 물체들이 상속하지 않는다는 사실 Function.prototype 기능으로 식별되지 않음을 의미합니다. instanceof 운영자; 그들의 생성자는 참조되지 않습니다 Function; 그리고 그들은 모든 것이 부족하다 Function.prototype.* 다음과 같은 방법 call 또는 apply. 그들의 내부 [[class]] 속성조차도 기본 객체와 마찬가지로 "기능"의 속성이 아닐 수도 있습니다 ([[class]]는 결과에서 추론 될 수 있습니다. Object.prototype.toString 값).

이것은 실제로 예상됩니다 호스트 객체는 필요하지 않습니다 기본 물체가하는 많은 것들을 구현하기 위해 (ECMA-262, 3rd ed.). 호스트 객체가 메소드 호출에 오류를 던지는 것이 완벽하게 허용됩니다 (예 : hostObject.hostMethod()); 또는 표준 연산자에게 피연산자로 전달할 때 delete (예 : delete hostObject.hostMethod). 보시다시피, 호출 가능한 호스트 오브젝트가 네이티브에서 상속받지 않는 것은 괜찮습니다. 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"]);

나는이 같은 문제를 겪었고 런타임에 덩어리 함수를 컴파일하여 올바른 수의 인수를 풀어서 해결했습니다 (이전 솔루션과 유사하지만 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);
};

분명히 IE의 JS 엔진 apply(). 그냥하는 것은 어떻습니까 eval() - 추악하지만 유일한 선택 인 것 같습니다.

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

당신이 사용한다면 언급 할 것이라고 생각했습니다 eval Ates Goral이 변수 이름으로 간주 될 예정인 배열의 문자열 인수에주의해야한다고 말했듯이.

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

그만큼 eval 라인이 전달됩니다

Master.Initialize(1,VC1)

VC1이 정의 된 변수가 아닌 경우 오류가 발생합니다. 리터럴을 전달하는 대신 배열 이름을 "롤"하는 것이 가장 좋습니다.

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
}

그래서 호출됩니다

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

그만큼 eval 그런 다음 통과됩니다

Master.Initialize(args[0],args[1]);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top