为了清楚起见,继承DynamicObject的类(当然是在C#中)与JavaScript的变量是动态的概念不同。 DynamicObject允许实现者以编程方式确定对象具有哪些成员,包括方法。
编辑:我了解JavaScript对象可以在运行时添加任何成员。这根本不是我所说的。这是一个C#示例,显示了DynamicObject的功能:
public class SampleObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = binder.Name;
return true;
}
}
dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".
当访问obj的成员时,它使用TryGetMember以编程方式确定成员是否存在以及它的值是什么。简而言之,成员的存在是在请求时确定的,而不是通过事先添加它来确定的。我希望这可以澄清一下这个问题。如果您想知道,我正在尝试确定是否可以在JavaScript中创建一个对象,当它使用函数调用语法时如下:
myAPI.uploadSomeData(data1, data2)
uploadSomeData调用转到类似函数的“TryGetMember”,它使用名称“uploadSomeData”执行$ .ajax调用以生成URL,返回值为结果。
答案 0 :(得分:2)
答案 1 :(得分:1)
JavaScript允许在for...in
循环中迭代对象的属性和方法。
您可以使用typeof
运算符确定它是一种方法。
<强> HTML:强>
<ul id="console"></ul>
<强> JavaScript的:强>
var Application = (function(app) {
app.constants = app.constants || {};
app.constants.PRINT_OBJ_TITLE = '[Printing an object]';
app.console = {
constants: {
SEPARATOR: new Array(50).join('-')
},
output: document.getElementById('console'),
log: function() {
var li = document.createElement('li');
li.innerHTML = Array.prototype.join.call(arguments, '');
this.output.appendChild(li);
},
printSeparator: function() {
this.log(this.constants.SEPARATOR);
}
};
app.printObj = function(obj) {
this.console.log(app.constants.PRINT_OBJ_TITLE);
for(var prop in obj) {
if(obj.hasOwnProperty(prop)) {
var propType = (typeof obj[prop] == 'function')
? 'function'
: 'property';
this.console.log(propType, ': ', prop);
}
}
this.console.printSeparator();
};
return app;
})(Application || {});
var obj = {},
app = Application;
obj.foo = function() {
alert("I'm a foo function!");
};
obj.bar = "I'm just a property";
app.printObj(obj);
<强>更新强>
所以你不应该期望JavaScript有如Java或C#那样的大量反射工具。 您可以通过某种方式模拟此类行为,但无论如何,您将无法创建特殊的JavaScript对象并调用其不存在的属性。唯一的方法是创建一个特殊的功能,实现开关,外观,地图等 - 任何允许使流动更动态的结构。
像这样exmaple。
您可以改进此逻辑并根据用户的操作,传入数据等动态向app.Stuff
添加其他属性和功能。因此,总体而言,您可以使用某种元构建智能灵活的系统 - 用JavaScript编程。
答案 2 :(得分:1)
我堆满了类似的问题,并写下了这段代码:
const dynamicFunc = (input) => {
const handler = {
get: (obj, prop) => {
// edge case when .toString() is calling for dynamic prop - just return any string
if (typeof prop === 'symbol') {
return () => "custom_dynamic_str";
}
const isPropExist = typeof obj[prop] !== 'undefined';
if (isPropExist) {
const val = obj[prop];
// for case, when we assigned our function to dynamic object, we should return it
if (val.__isSetAsFunction) {
return val.func;
}
// if value was created not by this method - return value
if (!val.__isDynamic) {
return val;
}
// function - our created dynamic func, let's create next chain part
if (typeof val === 'function') {
return dynamicFunc(val);
}
return val;
}
obj[prop] = () => dynamicFunc({});
obj[prop].__isDynamic = true;
return dynamicFunc(obj[prop]);
},
set(target, prop, value) {
// if our custom function was set to dynamic
if (typeof value === 'function') {
// wrap it to unwrap in get
target[prop] =
{
__isSetAsFunction: true,
func: value
};
}
else {
target[prop] = value;
}
return true;
},
apply: function (target, thisArg, argumentsList) {
return dynamicFunc({});
}
};
let proxy = new Proxy(input, handler);
return proxy;
};
return dynamicFunc(baseObj);
我在这里使用Proxy类作为基本解决方案,所以用两个词来说-每次尝试访问某个属性时,如果此属性尚不存在,它将创建该属性。是时候进行编辑了,因为我堆满了问题,需要解决这些问题,所以:)
示例:
let ob = dynamic();
ob.test1.test2.test3('hello from Belarus!','qwerty').test5.t('test');
//we could assign properties on the fly :
ob.myProp.pyProp2 = 2;
console.log(ob.myProp.pyProp2) // "1" will be outputed
// some tests using chai and chai-spies:
dynamic().genericProperties.anyFunc().myprop.test();
let obj = dynamic({ predefinedObjValue: 3 });
obj.prop1.prop2.test = 1;
obj.prop1.prop3.test = 2;
obj.prop2.myfunc = () => { };
expect(obj.prop1.prop2.test).to.be.equal(1);
expect(obj.prop1.prop3.test).to.be.equal(2);
expect(obj.predefinedObjValue).to.be.equal(3);
const myFuncSpy = chai.spy.on(obj.prop2, 'myfunc');
obj.prop2.myfunc();
expect(myFuncSpy).to.have.been.called();
,不会导致任何错误 另外,您可以定义自己的基础对象,并且不会被覆盖:
let ob = dynamic({mycustomProp : 1});
ob.test1.test2.test3('asdasd','tt').test5.t('test'); //without error
console.log(ob.mycustomProp) // "1" will be outputed
答案 3 :(得分:0)
编辑1: 您可以使用typeof检查方法是否存在: if(typeof(obj.methodName)!=“undefined”){ //调用methodName } 如果要专门检查函数,其类型将返回“function”。但是,我不知道有什么方法可以获得函数的签名,尽管如果你的函数很好地处理空值,JavaScript是相当宽容的。
原始答案 我相信Ethan Brown有这个权利,因为所有Javascript对象基本上只是变量的名称 - 值对,有时是函数。请尝试以下代码来警告任何给定对象的所有属性和方法的列表:
function obj(prop){
this.prop = prop;
this.setProp = function setProp(prop){this.prop = prop};
}
var myObj = new obj("something");
myObj.setProp("anything else");
var getKeys = function(obj){
var keys = [];
for(var key in obj){
keys.push(key);
}
return keys;
}
alert(getKeys(myObj));
请注意,这与Slashnick在How to list the properties of a JavaScript object中使用的程序相同