5

为了清楚起见,继承 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,返回值是结果。

4

4 回答 4

2

令人惊讶的是,仅仅几周的偶尔 JavaScript 研究后,我设法找到了两个答案:

ES6 代理

noSuchMethod

于 2012-09-16T15:37:55.353 回答
1
于 2012-08-27T23:10:19.473 回答
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];

                // if null or undefined was set
                if (val == null || typeof val === 'undefined') {
                     return val;
                }

                // if value was created not by this method - return value
                if (!val.__isDynamic) {
                    return val;
                }

                return dynamicFunc(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    

工作样本:https ://codesandbox.io/s/craky-liskov-myf65

于 2019-05-10T10:01:29.710 回答
0

编辑1:您可以使用typeof检查方法是否存在: If(typeof(obj.methodName)!= "undefined"){ //call methodName } 如果要专门检查函数,其类型将返回“功能”。但是,我不知道有什么方法可以获取函数的签名,尽管如果你的函数能很好地处理空值,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如何列出 JavaScript 对象的属性中使用的过程相同

于 2012-08-27T23:16:25.990 回答