Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/452.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 可以是getter或function的对象属性_Javascript - Fatal编程技术网

Javascript 可以是getter或function的对象属性

Javascript 可以是getter或function的对象属性,javascript,Javascript,我正在编写一个可链接库,我希望API允许将链的一部分作为静态值(使用默认值)调用,有时作为函数调用,以便可以将参数传递给它们 简化示例: var obj={}; var chainCache=[]; 反射.定义属性(obj,“颜色”{ 得到(){ chainCache.push('red'); 返回obj; } }) 反射.定义属性(obj,“背景”{ 得到(){ chainCache.push('black'); 返回obj; } }) 反射.定义属性(对象“结束”{ 值(){ var va

我正在编写一个可链接库,我希望API允许将链的一部分作为静态值(使用默认值)调用,有时作为函数调用,以便可以将参数传递给它们

简化示例:
var obj={};
var chainCache=[];
反射.定义属性(obj,“颜色”{
得到(){
chainCache.push('red');
返回obj;
}
})
反射.定义属性(obj,“背景”{
得到(){
chainCache.push('black');
返回obj;
}
})
反射.定义属性(对象“结束”{
值(){
var value=chainCache.join(“”);
chainCache.length=0;
返回值;
}
})

console.log(obj.color.background.end())//红-黑
我比预期的更仔细地研究了这个问题。看来随着时代的到来,这是可能的。以您的示例为基础:

let chainCache = [];
let obj = {
    color: new Proxy(()=>{}, {
        get: (target, prop) => {
            chainCache.push("red");
            if(prop === "background") {
                chainCache.push("black");
                return { end: obj.end };
            }
        },
        apply: (target, prop, args) => {
            if(args.length > 0) {
                chainCache.push(args.pop());
            } else {
                throw new Error("color expects argument if called like function");
            }
            return { background: new Proxy(()=>{}, {
                get: (target,prop) => { chainCache.push("black"); return obj.end;}
            })};
        }
    }),
    end: () => {
        let value = chainCache.join(" ");
        chainCache = [];
        return value;
    }
};
console.log(obj.color.background.end());
console.log(obj.color("#FF0").background.end());
console.log(obj.color().background.end());
在调试控制台中,您可以获得:

red black
#FF0 black
Error: color expects argument if called like function

本质上,颜色是一个封装匿名箭头函数的代理,如果颜色像属性一样访问,则调用
get()
trap;如果颜色作为函数访问,则调用
apply()
trap。这允许进行某种程度的元编程,就像您正在寻找的那样。

您需要将
obj
作为一个函数

函数只是一个对象,也可以具有属性-
obj.color
必须返回一个函数(对于
obj.color()
),该函数具有属性(对于
obj.color.background

但是不,当访问getter时,您还不知道它是否将用于方法调用-
obj.color()
是一个属性访问加上一个函数调用

var chainCache = [];
var obj = Object.defineProperties(function obj(...args) {
  chainCache.push(args);
  return obj;
}, {
  color: {
    get() {
      chainCache.push('color');
      return obj;
    }
  },
  background: {
    get() {
      chainCache.push('background');
      return obj;
    }
  },
  end: {
    value: function() {
      var res = chainCache.reduce((acc, val) =>
        Array.isArray(val)
          ? `${acc}(${val.join(',')})`
          : `${acc}.${val}`
      , "obj");
      chainCache.length = 0;
      return res;
    }
  }
})

我认为这是不可能的。你需要把
obj
变成一个函数。是的,我已经在我的代码中使用了代理,但这并不是我想要的。如果提供了参数,则代码不能使用默认值,因此第二个示例实际上是一个bug。此外,您可能应该编写
returnobj
,而不是
return{end:obj.end}
您还合并了
backgound
color
,但它们可能应该是分开的,因为我希望能够在
obj
的每个“键”上有条件地传递参数,我更新了我的示例。“red”出现的唯一原因是,在函数调用的代理中,我返回了属性。访问该属性会导致添加默认值。您可以像我上面所做的那样添加其他代理以避免这种情况。我只是把你的例子当作一个例子,我并没有试图设计一个功能齐全的API,所以我选择了快捷方式来获得你想要的语法。这应该回答了最初的问题,即是否可以根据调用方式将对象的属性视为函数或属性。感谢您的回答,我非常感谢您的输入。我想说的是,我问这个问题是关于我昨晚提出的一个项目,在这个项目中,我不想授权
color
方法在没有提供颜色参数的情况下返回一个随机颜色,而是要保持不强迫用户使用函数
()
braces@vsyncMicheals的答案有点过于复杂了,并根据他的示例通话模式特别定制。当您事先知道可用属性时,您根本不需要代理,使用getter是完全等效的。@vsync我不知道“控制台颜色”在哪里需要可以同时执行这两个操作的东西-您当前有
console.green.log()
console.random.log()
,对吗?我想去掉
random
并将其更改为
color
,然后用户可以选择传递一个参数,或者只是在属性中使用它:
console.color.big.bold.log()
以获得随机颜色。似乎是一个更好的API不?我同意这其中哪一个可能不值得这么做过于复杂,但我只是好奇在javascript中是否可以这样做,我在这里问过