关于javascript:’this’在函数里面的原型函数

'this' in function inside prototype function

本问题已经有最佳答案,请猛点这里访问。

我基本上有一个对象,通过它的原型扩展了一个函数。在该函数内部,存在另一个函数,但是当在这个嵌套函数中使用this时,它似乎不是指对象,而是指函数。

例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var sampleObject = function() {
 this.foo = 123;
}

sampleObject.prototype.getFoo = function() {
 var nested = function() {
  return this.foo;
 }
 return nested();
}

var test = new sampleObject();

window.alert(test.getFoo()); // undefined

this.foo不引用123值,但未定义,因为它是指嵌套函数,其中不存在foo。如何从嵌套函数访问123值?


1
2
3
4
5
6
7
sampleObject.prototype.getFoo = function() {
 var me = this;
 var nested = function() {
  return me.foo;
 }
 return nested;
}

通过在局部变量中保存this的值,可以使它显式地成为该函数和所有嵌套函数作用域的词汇上下文的一部分。因此,在调用"nested"时,内部函数将有自己的作用域(它自己的this值),但它仍然可以引用封闭作用域中的变量"me"。


这方面的常见工作是使用闭包

1
2
3
4
5
6
7
sampleObject.prototype.getFoo = function() {
  var _this = this;
  var nested = function() {
    return _this.foo;
   }
   return nested();
}

一些库添加方法来自动执行此操作

  • 原型添加了function.bind(http://prototypejs.org/doc/latest/language/function/prototype/bind/)
  • ext添加function.createdelegate(http://www.sencha.com/learn/manual:utilities:function createdelegate)
  • javascript 1.8.5添加了function.bind(https://developer.mozilla.org/en/javascript/reference/global_objects/function/bind)


在您的示例中,"this"指的是window对象,因为您在调用嵌套函数时没有指定另一个上下文,并且由于window.foo未定义而得到未发现。

你可以用三种方法来解决这个问题。

1-使用变量存储外部此-最常用的方法

1
2
3
4
5
6
7
sampleObject.prototype.getFoo = function() {
 var _this = this;
 var nested = function() {
  return _this.foo;
 }
 return nested();
}

2-使用将外部"this"绑定到内部的绑定方法

1
2
3
4
5
6
sampleObject.prototype.getFoo = function() {
 var nested = function() {
  return this.foo;
 }.bind(this);
 return nested();
}

3-使用可将上下文传递给函数的调用方法

1
2
3
4
5
6
SampleObject.prototype.getFoo = function() {
 var nested = function() {
  return this.foo;
 };
 return nested.call(this);
}

DR

使用箭头功能。自ECMAScript 6起提供:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var sampleObject = function() {
  this.foo = 123;
}

sampleObject.prototype.getFoo = function() {
  var nested = () => { // Changed this line.
    return this.foo;
  }
  return nested();
}

var test = new sampleObject();

window.alert(test.getFoo());

解释

这是arrow函数的主要优点之一。您的案件在"EDOCX1不具有约束力"〔0〕一节中有描述。引用说明:

Until arrow functions, every new function defined its own this value [...]
An arrow function does not create its own this context, so this has the original meaning from the enclosing context.


除了向var _this = this声明,我还看到代码执行var that = thisvar self = this

了解变量的范围很重要,因为它可能会产生意外的结果。


这是一个古老的问题,但为了完整性,我给出了另一个解决方案。另一种方法涉及函数绑定。

1
2
3
4
5
6
sampleObject.prototype.getFoo = function() {
 var nested = function() {
  return this.foo;
 }
 return nested.bind(this)();
}


ES6的一种方法是使用箭头函数。基本上,当您使用箭头函数时,它不会创建自己的"this"上下文。因此,使用"this"将引用父函数的上下文。代码的外观如下:

1
2
3
4
5
6
sampleObject.prototype.getFoo = function() {
    const nested = () => {
        return this.foo; //"this" refers to parent function's context
    }
    return nested;
}

这是javascript上的一个已知缺陷。通常的模式是将其分配给外部函数中的另一个变量(通常是self),然后从内部函数访问self。这是可行的。