سؤال

تسمح JavaScript بمعاملة الوظائف ككائنات - إذا قمت أولاً بتعريف متغير كدالة، فيمكنك بعد ذلك إضافة خصائص إلى تلك الوظيفة.كيف يمكنك القيام بالعكس وإضافة وظيفة إلى "كائن"؟

هذا يعمل:

var foo = function() { return 1; };
foo.baz = "qqqq";

عند هذه النقطة، foo() يستدعي الدالة، و foo.baz له قيمة "qqqq".

ومع ذلك، إذا قمت بجزء تعيين الخاصية أولاً، فكيف يمكنك بعد ذلك تعيين دالة للمتغير؟

var bar = { baz: "qqqq" };

ماذا يمكنني أن أفعل الآن لترتيب ذلك bar.baz للحصول على القيمة "qqqq" و bar() لاستدعاء الدالة؟

هل كانت مفيدة؟

المحلول

من السهل أن تشعر بالارتباك هنا، لكن لا يمكنك (بسهولة أو بوضوح أو بقدر ما أعرف) أن تفعل ما تريد.نأمل أن يساعد هذا في توضيح الأمور.

أولاً، يرث كل كائن في Javascript من كائن الكائن.

//these do the same thing
var foo = new Object();
var bar = {};

ثانيا، الوظائف نكون الكائنات في جافا سكريبت.على وجه التحديد، فهي كائن وظيفة.يرث كائن الوظيفة من كائن الكائن.تفحص ال منشئ الوظيفة

var foo = new Function();
var bar = function(){};
function baz(){};

بمجرد إعلان المتغير على أنه "كائن"، لا يمكنك (بسهولة أو بوضوح أو بقدر ما أعرف) تحويله إلى كائن دالة.ستحتاج إلى الإعلان عن كائن جديد من النوع Function (باستخدام مُنشئ الوظيفة، وتعيين متغير لوظيفة مجهولة وما إلى ذلك)، ونسخ أي خصائص للطرق من كائنك القديم.

أخيرًا، توقع سؤال محتمل، حتى بمجرد الإعلان عن شيء ما كوظيفة، لا يمكنك (على حد علمي) تغيير الوظيفة/المصدر.

نصائح أخرى

لا يبدو أن هناك طريقة قياسية للقيام بذلك، لكنها ناجحة.

لماذا ومع ذلك، هو السؤال.

function functionize( obj , func )
{ 
   out = func; 
   for( i in obj ){ out[i] = obj[i]; } ; 
   return out; 
}

x = { a: 1, b: 2 }; 
x = functionize( x , function(){ return "hello world"; } );
x()   ==> "hello world" 

ببساطة لا توجد طريقة أخرى لتحقيق ذلك ، والفعل

x={}
x() 

سيعود "خطأ في النوع".لأن "x" هو "كائن" ولا يمكنك تغييره.إنه أمر معقول مثل محاولة القيام به

 x = 1
 x[50] = 5
 print x[50] 

لن ينجح الأمر.1 هو عدد صحيح.الأعداد الصحيحة ليس لها طرق صفيف.لا يمكنك تحقيق ذلك.

أنواع الكائنات هي وظائف والكائن نفسه عبارة عن إنشاء مثيل للوظيفة.

  javascript:alert([Array, Boolean, Date, Function,
                       Number, Object, RegExp, String].join('\n\n'))

يعرض (في فايرفوكس):

function Array() {
    [native code]
}

function Boolean() {
    [native code]
}

function Date() {
    [native code]
}

function Function() {
    [native code]
}

function Number() {
    [native code]
}

function Object() {
    [native code]
}

function RegExp() {
    [native code]
}

function String() {
    [native code]
}

على وجه الخصوص، لاحظ كائن وظيفة، function Function() { [native code] }, ، يتم تعريفها على أنها علاقة تكرارية (تعريف متكرر يستخدم نفسه).

لاحظ أيضًا أن الإجابة 124402#124402 غير مكتمل فيما يتعلق 1[50]=5.يؤدي هذا إلى تعيين خاصية لكائن رقم ويكون جافا سكريبت صالحًا.يراقب،

javascript:
     alert([  [].prop="a",   true.sna="fu",   (new Date()).tar="fu",
                     function(){}.fu="bar",   123[40]=4,   {}.forty=2,
                         /(?:)/.forty2="life",   "abc".def="ghi"  ].join("\t"))

يعرض

a   fu  fu  bar 4   2   life    ghi

التفسير والتنفيذ بشكل صحيح وفقًا لـ "قواعد المشاركة" الخاصة بجافا سكريبت.

بالطبع هناك دائما التجاعيد و تتجلى بها =.غالبًا ما يكون الكائن "مختصرًا" لقيمته بدلاً من كيان كامل عند تعيينه لمتغير.هذه مشكلة تتعلق بالكائنات المنطقية والقيم المنطقية.

تعريف الكائن الصريح يحل هذه المشكلة.

javascript: x=new Number(1);  x[50]=5;  alert(x[50]);

يعد "التحميل الزائد" تمرينًا مشروعًا لجافا سكريبت ويتم دعمه بشكل صريح بآليات مثل prototyping على الرغم من أن تشويش التعليمات البرمجية يمكن أن يشكل خطراً.

ملاحظة أخيرة:

javascript: alert(  123 . x = "not"  );

javascript: alert( (123). x = "Yes!" );  /* ()'s elevate to full object status */

استخدم متغيرًا مؤقتًا:

var xxx = function()...

ثم انسخ جميع الخصائص من الكائن الأصلي:

for (var p in bar) { xxx[p] = bar[p]; }

أخيرًا قم بإعادة تعيين الوظيفة الجديدة بالخصائص القديمة للمتغير الأصلي:

bar = xxx;
var A = function(foo) {                                                                                                      
  var B = function() {                                                                                                       
    return A.prototype.constructor.apply(B, arguments);
  };
  B.prototype = A.prototype;                                                                                                 
  return B;                                                                                                                  
}; 

يسمح JavaScript بمعالجة الوظائف ككائنات-يمكنك إضافة خاصية إلى وظيفة.كيف تفعل العكس ، وتضيف وظيفة إلى كائن؟

يبدو أنك مرتبك بعض الشيء.الوظائف في جافا سكريبت، نكون أشياء.و المتغيرات نكون عامل.لن تتوقع أن ينجح هذا:

var three = 3;
three = 4;
assert(three === 3);

...فلماذا تتوقع أن تعيين دالة للمتغير الخاص بك من شأنه أن يحافظ بطريقة أو بأخرى على قيمته السابقة؟ولعل بعض الشروحات توضح لك الأمور:

// assigns an anonymous function to the variable "foo"
var foo = function() { return 1; }; 
// assigns a string to the property "baz" on the object 
// referenced by "foo" (which, in this case, happens to be a function)
foo.baz = "qqqq";

ملحوظة:تدوينة مكتوبة بأسلوب كيف قمت بحل المشكلة.لست متأكدًا بنسبة 100% من إمكانية استخدامه في حالة OP.

لقد وجدت هذا المنشور أثناء البحث عن طريقة لتحويل الكائنات التي تم إنشاؤها على الخادم وتسليمها إلى العميل بواسطة JSON/ajax.

الأمر الذي تركني فعليًا في نفس الموقف مثل OP، وهو الكائن الذي أردت تحويله إلى وظيفة حتى أتمكن من إنشاء مثيلات له على العميل.

في النهاية توصلت إلى هذا، والذي يعمل (حتى الآن على الأقل):

var parentObj = {}

parentObj.createFunc = function (model)
{
    // allow it to be instantiated
    parentObj[model._type] = function()
    {
        return (function (model)
        {
            // jQuery used to clone the model
            var that = $.extend(true, null, model);
            return that;
        })(model);
    }
}

والتي يمكن بعد ذلك استخدامها مثل:

var data = { _type: "Example", foo: "bar" };
parentObject.createFunc(data);
var instance = new parentObject.Example();

في حالتي، أردت بالفعل الحصول على وظائف مرتبطة بمثيلات الكائن الناتجة، وأن أكون قادرًا أيضًا على تمرير المعلمات في وقت إنشاء مثيل لها.

لذلك كان الكود الخاص بي:

var parentObj = {};
// base model contains client only stuff
parentObj.baseModel =
{
    parameter1: null,
    parameter2: null,
    parameterN: null, 
    func1: function ()
    {
        return this.parameter2;
    },
    func2: function (inParams) 
    {
        return this._variable2;
    }
}

// create a troop type
parentObj.createModel = function (data)
{
    var model = $.extend({}, parentObj.baseModel, data);
    // allow it to be instantiated
    parentObj[model._type] = function(parameter1, parameter2, parameterN)
    {
        return (function (model)
        {
            var that = $.extend(true, null, model);
            that.parameter1 = parameter1;
            that.parameter2 = parameter2;
            that.parameterN = parameterN;
            return that;
        })(model);
    }
}

وكان يسمى هكذا:

// models received from an AJAX call
var models = [
{ _type="Foo", _variable1: "FooVal", _variable2: "FooVal" },
{ _type="Bar", _variable1: "BarVal", _variable2: "BarVal" },
{ _type="FooBar", _variable1: "FooBarVal", _variable2: "FooBarVal" }
];

for(var i = 0; i < models.length; i++)
{
    parentObj.createFunc(models[i]);
}

وبعد ذلك يمكن استخدامها:

var test1 = new parentObj.Foo(1,2,3);
var test2 = new parentObj.Bar("a","b","c");
var test3 = new parentObj.FooBar("x","y","z");

// test1.parameter1 == 1
// test1._variable1 == "FooVal"
// test1.func1() == 2

// test2.parameter2 == "a"
// test2._variable2 == "BarVal"
// test2.func2() == "BarVal"

// etc
var bar = { 
    baz: "qqqq",
    runFunc: function() {
        return 1;
    }
};

alert(bar.baz); // should produce qqqq
alert(bar.runFunc()); // should produce 1

أعتقد أنك تبحث عن هذا.

يمكن كتابتها أيضًا على النحو التالي:

function Bar() {
    this.baz = "qqqq";
    this.runFunc = function() {
        return 1;
    }
}

nBar = new Bar(); 

alert(nBar.baz); // should produce qqqq
alert(nBar.runFunc()); // should produce 1
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top