Как преобразовать "объект” в функцию в JavaScript?
-
02-07-2019 - |
Вопрос
JavaScript позволяет рассматривать функции как объекты - если вы сначала определяете переменную как функцию, вы можете впоследствии добавить свойства к этой функции.Как вы делаете обратное и добавляете функцию к "объекту"?
Это работает:
var foo = function() { return 1; };
foo.baz = "qqqq";
На данный момент, foo()
вызывает функцию, и foo.baz
имеет значение "qqqqq".
Однако, если вы сначала выполните часть назначения свойства, как вы впоследствии назначите функцию переменной?
var bar = { baz: "qqqq" };
Что я могу сделать сейчас, чтобы организовать bar.baz
иметь значение "qqqq" и bar()
чтобы вызвать функцию?
Решение
Здесь легко запутаться, но вы не можете (легко или ясно, или насколько я знаю) делать то, что вы хотите.Надеюсь, это поможет прояснить ситуацию.
Во-первых, каждый объект в Javascript наследуется от Object object.
//these do the same thing
var foo = new Object();
var bar = {};
Во-вторых, функции ЯВЛЯЮТСЯ объекты в Javascript.В частности, они являются функциональным объектом.Объект Function наследуется от объекта Object object.Оформить заказ Конструктор функций
var foo = new Function();
var bar = function(){};
function baz(){};
Как только вы объявляете переменную "Объектом", вы не можете (легко или явно, насколько я знаю) преобразовать ее в объект-функцию.Вам нужно было бы объявить новый объект типа Function (с конструктором функции, присвоением переменной анонимной функции и т.д.) и скопировать все свойства методов из вашего старого объекта.
Наконец, предвосхищая возможный вопрос, даже после того, как что-то объявлено как функция, вы не можете (насколько я знаю) изменить FunctionBody / source .
Другие советы
Похоже, стандартного способа сделать это не существует, но это работает.
ОДНАКО почему, вот в чем вопрос.
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'))
отображает (в FireFox):
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
.Это ДЕЙСТВИТЕЛЬНО присваивает свойство объекту Number и является допустимым Javascript.Наблюдать,
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.
Конечно, всегда есть морщинка, которая проявляется =
.При присвоении переменной объекту часто происходит "короткое замыкание" на его значение, а не на полноценную сущность.Это проблема с логическими объектами и логическими значениями.
Явная идентификация объекта решает эту проблему.
javascript: x=new Number(1); x[50]=5; alert(x[50]);
"Перегрузка" является вполне законным упражнением Javascript и явно поддерживается такими механизмами, как 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 позволяет рассматривать функции как объекты - вы можете добавить свойство к функции.Как вы делаете обратное и добавляете функцию к объекту?
Вы, кажется, немного сбиты с толку.Функции в 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%, что это можно использовать в случае операционной системы.
Я нашел этот пост, когда искал способ конвертировать объекты, созданные на сервере и доставленные клиенту с помощью 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