【问题标题】:How to get object props function caller?如何获取对象道具函数调用者?
【发布时间】:2020-04-19 14:34:27
【问题描述】:

(求助者注意:这个问题可能没有解决方案)

大家好,

我正在解决我给自己的一个小挑战。当我遇到一个看似不可能完成的任务时。挑战如下。

顶级水平
有一个使用闭包来模拟类的函数。 (类我的意思是当你声明一个新类时你在 C++ 或 C# 中得到的东西。)顶部函数将返回一个内部函数,该函数具有道具并返回更改这些道具的方法。这意味着我无法直接访问道具。 (当你在传统类的 private 下声明变量时你会得到什么)

代码

const Person = function() { //outer function
  const closures = () => { // inner function 
    let firstName, lastname, age, gender; // "class" properties (props) unknown to Person

    return { // returns the methods I can use to update or get the props + functionalities

      //setters - can set the properties of closures
      setFirstName: (name) => {
        firstName = name;
      },
      setLastName: (surname) => {
        lastname = surname;
      },
      setAge: (newAge) => {
        newAge > 0 && newAge < 150 ? age = newAge : console.warn(`Age has not been set, ${newAge} is out of range`);
      },
      setGender: (newGender) => {
        const personExist = (firstName || lastname);
        personExist? gender = newGender : console.warn("This person does not exist, you need to define their first or last name . . .");

        personExist?checkGender(newGender) ? gender = newGender : console.warn(`Gender has not been set. ${newGender} is not supported at the moment.`) : null;
        ;
      },

      //getters - can get the properites of closures
      getFirstName: () => firstName,
      getLastName: () => lastname,
      getAge: ()=> age,
      getGender: ()=>gender,

      //Functionalities -- things that a Person obj can do
      introduction: () => {
        let p1 = firstName ? `Grettings, my name is ${firstName}` : lastname ? `Last Name is ${lastname}` : '';
        let p2 = firstName ? 
                  lastname ? ` ${lastname}.` : '' :
                  lastname ? `. You can refer to me as ${lastname}`: '';
        let p3 = age? `I am ${age} years-old.` : '';

        let p4 = p1 != '' || p2 != '' ? `${lastname?`${p1}${p2} ${p3}`: `${p1}.${p2} ${p3}`}` : "I do not know me . . .";

        return `${p4}`
      },

      speak: function to(Person) { // troublesome part

        if(typeof Person == 'object'){
          console.log(`> ${Person.introduction()}`); 
          // console.log(name.caller)
          // console.log(name.prototype)
          // everything was going well till this part of the challenge, where I am trying to get name.caller so i can access its props
        } else {
          console.warn(`Cannot talk to ${Person} because ${Person} is not of type person.`)
        }
      }
    }
  }

  return closures();
}


// this is the entire code, feel free to use it in anyway whatsoever. 

问题
我正在努力解决的最后一个挑战是当我尝试实现“说话”功能时。

-- 预期行为
Person 实例(不是第一个创建的)将调用 speak,传入另一个 person 实例。 在说话中,参数将使用声明的方法之一进行自我介绍。然后来电者会自我介绍。

--麻烦的部分
我无法访问“to's”(说话的函数子名称)调用者。 (如果您想知道,我需要给它一个子名称,因为如果我尝试调用“speak”,它将产生错误。)简单的解决方案是将调用者作为参数传入,但我想能够使用调用者方法访问它。

例如下面的代码


let rian = Person(); 
rian.setFirstName("Rian");
rian.setLastName("Arias");
rian.setGender("Male");
rian.setAge(30);


let pepe = Person();
pepe.setFirstName("Pepe");
pepe.setLastName("Lopez"); 
pepe.setGender("Male");

pepe.speak(dario); // will not work because I haven't been able to get 'caller' to work 

应该输出以下内容

> 问候,我的名字是达里奥·阿里亚斯。我20岁了。

【问题讨论】:

  • 我想你的意思是pepe.speak(rian); 作为最后一行? checkGender 是什么?
  • 如果您希望能够确定传递给speak 的参数是另一个Person,您还需要另一个闭包。
  • 我只想在repl 中分享您的代码。
  • checkGender 是一种接受输入的方法,如果该输入是有效的性别,则返回 true,否则返回 false。我确实是想使用 Rian,当我写这篇文章时我很着急,这就是为什么整个解释都缺乏。

标签: javascript reactjs closures


【解决方案1】:

您可以通过this 访问当前人员实例:

console.log(`> ${this.introduction()}`); 

function checkGender(gender) { return ["Male", "Female"].includes(gender) }

const Person = function() { //outer function
  const closures = () => { // inner function 
    let firstName, lastname, age, gender; // "class" properties (props) unknown to Person
    

    return { // returns the methods I can use to update or get the props + functionalities

      //setters - can set the properties of closures
      setFirstName: (name) => {
        firstName = name;
      },
      setLastName: (surname) => {
        lastname = surname;
      },
      setAge: (newAge) => {
        newAge > 0 && newAge < 150 ? age = newAge : console.warn(`Age has not been set, ${newAge} is out of range`);
      },
      setGender: (newGender) => {
        const personExist = (firstName || lastname);
        personExist? gender = newGender : console.warn("This person does not exist, you need to define their first or last name . . .");

        personExist?checkGender(newGender) ? gender = newGender : console.warn(`Gender has not been set. ${newGender} is not supported at the moment.`) : null;
        ;
      },

      //getters - can get the properites of closures
      getFirstName: () => firstName,
      getLastName: () => lastname,
      getAge: ()=> age,
      getGender: ()=>gender,

      //Functionalities -- things that a Person obj can do
      introduction: () => {
        let p1 = firstName ? `Grettings, my name is ${firstName}` : lastname ? `Last Name is ${lastname}` : '';
        let p2 = firstName ? 
                  lastname ? ` ${lastname}.` : '' :
                  lastname ? `. You can refer to me as ${lastname}`: '';
        let p3 = age? `I am ${age} years-old.` : '';

        let p4 = p1 != '' || p2 != '' ? `${lastname?`${p1}${p2} ${p3}`: `${p1}.${p2} ${p3}`}` : "I do not know me . . .";

        return `${p4}`
      },

      speak: function to(Person) { // troublesome part

        if(typeof Person == 'object'){
          console.log(`> ${Person.introduction()}`); 
          console.log(`> ${this.introduction()}`); 
          // console.log(name.caller)
          // console.log(name.prototype)
          // everything was going well till this part of the challenge, where I am trying to get name.caller so i can access its props
        } else {
          console.warn(`Cannot talk to ${Person} because ${Person} is not of type person.`)
        }
      }
    }
  }
  return closures();
}

let rian = Person(); 
rian.setFirstName("Rian");
rian.setLastName("Arias");
rian.setGender("Male");
rian.setAge(30);


let pepe = Person();
pepe.setFirstName("Pepe");
pepe.setLastName("Lopez"); 
pepe.setGender("Male");

pepe.speak(rian);

【讨论】:

  • 这与 Repl.it 无关。如果你得到了窗口对象,这意味着你没有用点表示法调用函数,比如pepe.speak(),但可能传递了函数引用,比如setTimeout(pepe.speak),在这种情况下,函数不会被调用与pepe 一样this。有关详细说明,请参阅how does the this keyword work
【解决方案2】:

所以我相信我发现了你的错误。作为 js 中的一个好的经验法则,每个名称最好只有 1 个变量。这可能只是从你的眼中溜走,我一直这样做,但你有两个名为 Person 的变量。我把你的说话功能改成了这样:

speak: function (p) { // troublesome part
    if(typeof p == 'object'){
      console.log(`> ${p.introduction()}`);
    } else {
      console.warn(`Cannot talk to ${p} because ${p} is not of type person.`)
    }
  }

它就像一个魅力。我还删除了对“checkGender”的引用,并将“dario”更改为“rian”,它输出了我相信你想要的东西。另外,我删除了函数的“to”子名称,因为我不确定您为什么想要/需要子名称。

【讨论】:

    猜你喜欢
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多