简体   繁体   English

Javascript:为什么私有函数里面的“this”指的是全局范围?

[英]Javascript: why “this” inside the private function refers to the global scope?

Consider the following code: 请考虑以下代码:

function A() {}    

A.prototype.go = function() {
    console.log(this); //A { go=function()}

    var f = function() {
         console.log(this);  //Window              
    };

    f();
}

var a = new A();
a.go();

Why does 'this' inside function 'f' refers to the global scope? 为什么函数'f'中的'this'指的是全局范围? Why it is not the scope of function 'A' ? 为什么它不是功能'A'的范围?

JavaScript has a different concept of what the special name this refers to than most other programming languages do. JavaScript有什么样的特殊名称的不同概念, this是指比大多数其他编程语言做。 There are exactly five different ways in which the value of this can be bound in the language. 五种不同的方式可以将this值绑定在语言中。

The Global Scope 全球范围

this;

When using this in global scope, it will simply refer to the global object. 当使用this在全球范围内,它会简单地引用全局对象。

Calling a Function 调用函数

foo();

Here, this will again refer to the global object. 在这里, this将再次引用全局对象。

ES5 Note: In strict mode, the global case no longer exists. ES5注意:在严格模式下,全局案例不再存在。 this will instead have the value of undefined in that case. 在这种情况下, this将取代undefined的值。

Calling a Method 调用方法

test.foo(); 

In this example, this will refer to test . 在这个例子中, this将参考test

Calling a Constructor 调用构造函数

new foo(); 

A function call that is preceded by the new keyword acts as a constructor. new关键字开头的函数调用充当构造函数。 Inside the function, this will refer to a newly created Object . 在函数内部, this将引用新创建的 Object

Explicit Setting of this 显式设置this

function foo(a, b, c) {}

var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3

When using the call or apply methods of Function.prototype , the value of this inside the called function gets explicitly set to the first argument of the corresponding function call. 当使用Function.prototypecallapply方法时,被调用函数内的this值被显式设置为相应函数调用的第一个参数。

As a result, in the above example the method case does not apply, and this inside of foo will be set to bar . 其结果是,在上述例子中所述方法的情况下 适用,并且this内部foo将被设定为bar

Note: this cannot be used to refer to the object inside of an Object literal. 注意: this 不能用于引用Object文本中的Object So var obj = {me: this} will not result in me referring to obj , since this only gets bound by one of the five listed cases. 所以var obj = {me: this} 不会导致me引用obj ,因为this只会受到列出的五个案例之一的约束。

Common Pitfalls 常见的陷阱

While most of these cases make sense, the first one is to be considered another mis-design of the language because it never has any practical use. 虽然大多数这些案例都有意义,但第一个案例被认为是另一种错误的语言设计,因为它从未有任何实际用途。

Foo.method = function() {
    function test() {
        // this is set to the global object
    }
    test();
}

A common misconception is that this inside of test refers to Foo ; 一个常见的误解是, this test内部是指Foo ; while in fact, it does not . 事实上,事实并非如此

In order to gain access to Foo from within test , it is necessary to create a local variable inside of method which refers to Foo . 为了从test获得对Foo访问,有必要在method内部创建一个引用Foo的局部变量。

Foo.method = function() {
    var that = this;
    function test() {
        // Use that instead of this here
    }
    test();
}

that is just a normal variable name, but it is commonly used for the reference to an outer this . that只是一个普通的变量名,但它通常用于引用外部的this In combination with closures, it can also be used to pass this values around. 与闭合相结合,它也可用于传递this值。

Assigning Methods 分配方法

Another thing that does not work in JavaScript is function aliasing, which is assigning a method to a variable. 并不在JavaScript中工作的另一件事情是功能走样,这是赋值给一个变量的方法。

var test = someObject.methodTest;
test();

Due to the first case, test now acts like a plain function call; 由于第一种情况, test现在就像一个普通的函数调用; therefore, this inside it will no longer refer to someObject . 因此, this内部将不再引用someObject

While the late binding of this might seem like a bad idea at first, in fact, it is what makes prototypal inheritance work. 虽然后期绑定this似乎是一个坏主意,首先,在事实上,这是什么使原型继承工作。

function Foo() {}
Foo.prototype.method = function() {};

function Bar() {}
Bar.prototype = Foo.prototype;

new Bar().method();

When method gets called on a instance of Bar , this will now refer to that very instance. method被调用上的例子Barthis现在指的是非常的实例。

Disclaimer: Shamelessy stolen from my own resources at http://bonsaiden.github.com/JavaScript-Garden/#function.this 免责声明: Shamelessy从我自己的资源中偷走了http://bonsaiden.github.com/JavaScript-Garden/#function.this

The reason why is you are invoking f as a function and not a method . 你之所以将f作为一个function而不是一个method来调用。 When invoked as a function this is set to window during the execution of the target 当作为函数调用this被设定为window的目标的执行期间

// Method invocation.  Invoking a member (go) of an object (a).  Hence 
// inside "go" this === a
a.go();

// Function invocation. Invoking a function directly and not as a member
// of an object.  Hence inside "f" this === window
f(); 

// Function invocation. 
var example = a.go;
example();

The scope of all functions is window . 所有功能的范围都是window

To circumvent that, you can do this: 为了规避这一点,你可以这样做:

function A() {}    

A.prototype.go = function() {
    var self = this;
    console.log(self); //A { go=function()}
    var f = function() {
         console.log(self);  //A { go=function()}           
    };

    f();
}

Because function f() is not called without any object reference. 因为没有任何对象引用就不会调用函数f() Try, 尝试,

f.apply(this);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM