JavaScript中的获取示例父属性访问器链

dgiusagp  于 2023-03-21  发布在  Java
关注(0)|答案(3)|浏览(92)

我有理由相信我想要的是可能的,但我没有正确地表达,并且很难找到它。我试图实现的是:
假设我有一个通用对象obj,如下所示:

const obj={
  job:function(){},
  age:function(){},
  school:function(){}
}

我希望能够调用它作为可变长度的对象属性的链式列表,然后在final方法中访问该链。一些示例:
日本

obj.job.school.age.job.school() // in the school body, I should know  'job.school.age.job' and that I am `school`
obj.job.school() // in the school body, I should know 'job' and that I am `school`
obj.job.job.job() // in the job body, I should know 'job.job' and that I am `job`

格式无关紧要。它不必是字符串。主要的一点是,在最终方法中,我应该知道在这个示例上到达我的属性链。属性应该能够作为函数或普通属性进行链接。
在我看来,有两个问题需要解决。第一个是链接部分。我想我已经解决了这一部分:日本

Object.setPrototypeOf(obj.job,obj)
Object.setPrototypeOf(obj.school,obj)
Object.setPrototypeOf(obj.age,obj)

这使得对象在每个关键点都可以动态链接。例如,它允许:

obj.job.job.school.job.age.age.school.job.school.age.age.job()

但是我被第二部分卡住了,那就是知道我们是如何到达方法体内部的,所以在上面,最后一个job方法,应该知道它是job,在这个示例上,它前面的属性是:job.job.school.job.age.age.school.job.school.age.age .
我希望这不是太混乱。如果有什么不清楚我会编辑。

68de4m5k

68de4m5k1#

锁链不是魔法当你说

a.b.c()

这真的和

let x = a.b
x.c()

在这里,obj有3个键,每个键都是一个函数,如果每个函数返回this,那么你可以将它们链接起来,但是你还必须调用这个函数,而不仅仅是给予它的键:

const obj={
  job: () => {/* do something */ return obj},
  age: () => {/* do something */ return obj},
  school: () => {/* do something */ return obj}
}

// you can now chain them because each returns 'obj'
obj.job().job().school().job().age().age().school().job().school().age().age().job();

// but doing this won't work since obj.job returns the job function itself, not obj
obj.job.job();
// gives: Uncaught TypeError: obj.job.job is not a function
2sbarzqh

2sbarzqh2#

根据你的问题,似乎你想跟踪函数调用沿着实现链接。这是一个可能的解决方案,你的问题。也许它可以改进,但它会为你提供基本的想法。

问题01:

我们需要链接行为,所以我们是这样做的。

const email_validator = {
    tld: function(){ return this;},
    min: function(length){ return this;},
    max: function(length){ return this; }
}

请确保使用常规函数,因为它们将按预期工作,箭头函数将在Web浏览器中导致问题。

问题02

跟踪我们的链条。

const email_validator = {
    // Regular functions
    tld: function(){ this.addToStack(this.tld); return this;},
    min: function(length){ this.addToStack(this.min); return this;},
    max: function(length){ this.addToStack(this.max); return this; },

    // We will keep track of chain.
    stack: [],

    // The function needs to be after each function call.
    addToStack: function(func){ this.stack.push(func); }
}

上面的代码将每个函数调用存储在一个数组中,只要确保在每个函数之后调用addToStack函数,然后返回这个。
如果你想跟踪字符串而不是函数,你可以传递字符串而不是函数。或者根据你的需要改变它。
我希望上面的内容能为您提供一些如何做到这一点的想法。

用法

下面是如何使用上面的代码:

const email_validator = {
    // Regular functions
    tld: function(){ this.addToStack(this.tld); return this;},
    min: function(length){ this.addToStack(this.min); return this;},
    max: function(length){ this.addToStack(this.max); return this; },

    // We will keep track of chain.
    stack: [],

    // The function needs to be after each function call.
    addToStack: function(func){ this.stack.push(func); }
}

// This will contain stack of functions.
const history = email_validator.tld().tld().max().tld().stack;

// Print in format: tld.tld.max
const message = history.map(item => item.name).join(".");
console.log(message); // tld.tld.max
qxsslcnc

qxsslcnc3#

我知道这个问题很老了,但我觉得这个问题值得回答-这是否完成了你想做的事情?:

function the_obj() {
  console.log(...arguments)
  console.log(the_obj.accessStack)
  the_obj.accessStack.splice(0, the_obj.accessStack.length)
}
the_obj.accessStack = []

Object.defineProperty(the_obj, 'job', {
  get: function() {
    the_obj.accessStack.push('job')
    return the_obj
  },
})

Object.defineProperty(the_obj, 'school', {
  get: function() {
    the_obj.accessStack.push('school')
    return the_obj
  },
})

Object.defineProperty(the_obj, 'age', {
  get: function() {
    the_obj.accessStack.push('age')
    return the_obj
  },
}) 
   
the_obj.job.school.age.job.school() // ['job', 'school', 'age', 'job', 'school']

相关问题