Javascript 为什么;这";在通过逻辑运算符调用的函数中是否未定义?

Javascript 为什么;这";在通过逻辑运算符调用的函数中是否未定义?,javascript,Javascript,以下代码()不起作用 "use strict"; //without strict "this" works, but it refers to window object let person = { name : "Shimon", logName : function(){ //console.log("test") //this works console.log(this.name); //doesn't work } }; //person.logNa

以下代码()不起作用

"use strict"; //without strict "this" works, but it refers to window object

let person = {
  name : "Shimon",
  logName : function(){
    //console.log("test") //this works
    console.log(this.name); //doesn't work
  }
};

//person.logName(); //works
(false || person.logName)(); //doesn't work. Uncaught TypeError: Cannot read property 'name' of undefined
我想了解原因。
当我调用
(false | | person.logName)()时
我想调用
person.logName()
,它确实调用了。
那么为什么我不能在这个方法中使用
this

适用于实例化的类/函数。在您的情况下,必须将对象视为静态对象,如:

let person = {
  name : "Shimon",
  logName : function(){
    console.log(person.name);
  }
};

如果您想要这种行为,您可以使用类或原型内在性

班级人员{
建造师(姓名){
this.name=名称;
}
logName(){
console.log(this.name);
}
}

职能人员(姓名){
this.name=名称;
}
person.prototype.logName=函数(){
console.log(this.name);
}

这就是Javascript语义的行为方式。除非从附加到
的对象调用该方法,否则无法在函数范围内解析该

你的例子是:

(false || person.logName)();
可以改写为:

var func = person.logName;
func();
在这里,您可以直观地看到有一个中间步骤,
logName()
person
分离。这会产生一个副作用,即删除
上下文


有一些方法可以在“分离”函数上强制执行
上下文。其中之一是允许将
绑定到任何函数

(false || person.logName.bind(person))();
(false || person.logName).call(person);
这里创建了一个新函数,将
person
绑定为
this
,以实现所需的行为。或者,您可以使用来避免创建新函数

(false || person.logName.bind(person))();
(false || person.logName).call(person);

这在您设计的用例中起作用,但可能不适合您的实际用例,因为当您“分离”的函数不是来自同一个对象时,您将需要将不同的对象作为
参数传递。

JavaScript引擎有4条规则来确定
引用

  • New Bound:当前函数是否使用
    New
    关键字调用
  • 显式绑定:是否使用
    function#call
    function#apply
    调用函数
  • 隐式绑定:函数是否直接在其所属对象上
  • 默认值:如果处于严格模式
    未定义
    否则
    全局
  • 在您的情况下,
    person.logName()
    属于第三类,因此
    引用被设置为
    person
    的值
    但在另一种情况下,行
    (false | person.logName)(
    相当于
    var x=false | person.logName;x()。这是因为您正在使用表达式获取函数,因此上下文丢失。
    因此,您需要使用
    person.logName()
    (false | | person.logName)。调用(person)

    下面是一个更复杂的示例:

    var actionMap={
    0:函数(){
    log(this==actionMap?“actionMap”:“global”);
    },
    1:函数(){
    log(this==actionMap?“actionMap”:“global”);
    },
    };
    函数其他(){
    log(this==actionMap?“actionMap”:“global”);
    }
    actionMap[0]();//作品
    (actionMap[0])();//有效,括号被忽略
    (actionMap[0]| | actionMap[1])();//上下文在表达式中丢失
    (动作图[2]| |动作图[1])();//上下文在表达式中丢失
    (actionMap[2]| | actionMap[1])。调用(actionMap);//如果有效,则显式调用上下文
    var boundOther=other.bind(actionMap);
    
    (boundOther | | actionMap[1])();//函数已绑定
    可能与此名称重复,而不是记录此名称。你可以把它还回去。es2015之前的标准可能存在问题,您将其称为self。因此,生成es2015方法代替person={name:“Simon”,logname(){返回this.name}}@bhspencer这似乎是一个非常全局性的问题。我在那里找不到一点道理。如果你能详细说明一下,我将不胜感激。非常好的解释。谢谢