当与函数对象一起使用时,为什么'this'被区别对待?

cow*_*tor -1 javascript properties this

在试图理解JavaScript中的'this'关键字时,我看了很多资源,包括这个流行的Stack Overflow问题的答案: "this"关键字如何工作?

我不知道我是否误解了某些东西,但我读过的所有内容似乎都是不完整的并且缺少一条规则:即使函数是对象,对于函数对象与其他对象,"this"的处理方式也不同.

请考虑以下代码:

var object = {};
object.name = "object";
object.logMyName = function() { 
  console.log(this.name);
};
object.logMyName();
Run Code Online (Sandbox Code Playgroud)

因为在对象('对象')上调用函数('logMyName'),所以'this'被设置为调用函数('logMyName')的对象('object').

现在考虑以下代码:

var funcObject = function() {};
funcObject.name = "funcObject";
funcObject.logMyName = function() { 
  console.log(this.name);
};
funcObject.logMyName();
Run Code Online (Sandbox Code Playgroud)

尽管在对象('funcObject')上调用了一个函数('logMyName'),但'this' 未设置为调用函数('logMyName')的对象('funcObject').

为什么存在这种对象类型之间的差异,为什么很少/从未讨论过?

Ori*_*iol 5

那是因为函数有一个特殊的name属性.

该name属性的值是一个描述函数的String.该名称没有语义意义,但通常是一个变量或属性名称,用于在ECMAScript代码中的定义点引用该函数.此属性具有{[[Writable]]:false,[[Enumerable]]:false,[[Configurable]]:true } 属性.

该属性不可写,因此您的分配将被忽略.

但是,由于它是可配置的,您可以重新定义它:

var funcObject = function() {};
Object.defineProperty(funcObject, 'name', {
  configurable: true,
  value: "funcObject"
});
funcObject.logMyName = function() { 
  console.log(this.name);
};
funcObject.logMyName(); // logs "funcObject"
Run Code Online (Sandbox Code Playgroud)

请注意,在ES6将其标准化为可配置之前,一些旧浏览器将其实现为不可配置,因此上述代码可能无效.