جافا سكريبت:المشكلة مع ActiveX الكائن تطبيق () وظيفة
-
07-07-2019 - |
سؤال
لدي ActiveX كائن (ماجستير) و ترغب في استدعاء وظائف حيوي على ذلك.للقيام بذلك يجب استخدام تطبيق() وظيفة.ولكن للأسف Explorer يقول لي شيئا على غرار:"هذا لا يعتمد الكائن هذه الطريقة".شخص ما يمكن أن تعطيني تلميحا ما يمكنني فعله ؟
(هذا الاختبار يمكنك أيضا استخدام فلاش صغير وجوه سيد الاتصال "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 هذا هو تطبيق() وظيفة في العمل:
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 على وقتك الشرح المستفيض!للأسف لم أتمكن من الحصول عليه العمل بهذه الطريقة(يعمل من أجل alertbox على الرغم من) لكنه قادني إلى فكرة استخدام وكيل الدرجة.انها ليست الطريقة الأكثر أناقة لأنه يجب أن نقدم كل وظيفة من وجوه أريد استخدام لكنه يعمل وأنها لا تنطوي على 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) هو أنها لا ترث من Function.prototype
(و في كثير من الأحيان لا من أعلى مستوى Object.prototype
).استضافة بعض الكائنات التي قد تبدو مثل وظائف في الواقع لا علاقة لها وظائف إلا أنها يمكن أن يسمى.حقيقة أن هذه الكائنات لا ترث من Function.prototype
يعني أنها تفشل في التعرف على الوظائف مع instanceof
المشغل ؛ أن منشئ هو عدم الرجوع Function
;وأنهم يفتقرون إلى كل من Function.prototype.*
أساليب مثل call
أو apply
.حتى الداخلية [[الصف]] الخاصية قد لا يكون من "وظيفة", كما هو الحال مع أي كائن أصلي (لاحظ أن [[الصف]] يمكن استنتاجها من نتيجة Object.prototype.toString
القيمة).
هذا هو في الواقع الأمطار, منذ المضيف الكائنات غير مطلوبة لتنفيذ العديد من الأشياء التي مواليد الأشياء (كما في ECMA-262, 3rd ed.).هو تماما يسمح لمجموعة كائن إلى رمي الخطأ على استدعاء الأسلوب (مثل hostObject.hostMethod()
);أو عندما يمر على أنها المعامل على مستوى شركات مثل delete
(مثلا ، delete hostObject.hostMethod
).كما يمكنك أن ترى, بل هو أيضا طيب بالنسبة للاستدعاء المضيف الكائنات لا يرث من الأم Function.prototype
.
هذه لا يمكن التنبؤ بها (حتى الآن متوافقة تماما) السلوك هو في الواقع واحدة من الأسباب الرئيسية لماذا المضيف الكائنات تكبير يوصى ضد.
ولكن مرة أخرى إلى 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"]);
وكان لي نفس هذه المشكلة وأنا حلها عن طريق وضع الدالة thunk في وقت التشغيل في انبسط العدد الصحيح من الحجج (على غرار الحل السابق، ولكن من دون تقييد أن مؤشر كائن اكتف يجب أن يكون في عالمي متغير).
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);
};
ويبدو أن محرك JS IE للا يرى ظائف اكتف ككائنات وظيفة جافا سكريبت التي يمكنك الاتصال apply()
. ماذا عن مجرد القيام على eval()
- على الرغم من القبيح، يبدو أن لديك الخيار الوحيد
function invoke(objectName, fnName, args) {
return eval(objectName + "." + fnName + "(" + args + ")");
}
وبس كنت أذكر أن في حالة استخدام طريقة eval
كما قال آتش غورال عليك أن تكون حذرا من الحجج سلسلة في مجموعة الخاصة بك لأنها سوف ينظر أسماء المتغيرات، على سبيل المثال
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]);