search
HomeWeb Front-endJS Tutorialthis in JavaScript!

this in JavaScript!

Feb 04, 2017 pm 04:16 PM

Global execution

First, let’s see what this is in the global environment:

first. Browser:

console.log(this);

// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

You can see that the window object is printed;

second. node:

console.log(this);

// global

You can see that the global object is printed;

Summary: In the global scope, its this executes the current global object (Window on the browser side, global in node).

Execution in function

Pure function call

This is the most common way to use a function:

function test() {
  console.log(this);
};
test();
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

We can see that a function is When called directly, it is a global call, and its this points to the global object;

Strict mode 'use strict';

If a pure function call is executed in strict mode, Then this here will not point to the global world, but undefined. This approach is to eliminate some imprecise behaviors in js:

'use strict';
function test() {
  console.log(this);
};
test();
// undefined

Of course, it would be better to put it in an immediate execution function , to avoid polluting the global situation:

(function (){
  "use strict";
 console.log(this);
})();
// undefined

Called as a method of an object

When a function is called as a method of an object:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this.name);
  }
}
obj.foo();
// 'qiutc'

At this time, this points to The current object;

Of course, we can also do this:

function test() {
  console.log(this.name);
}
var obj = {
  name: 'qiutc',
  foo: test
}
obj.foo();
// 'qiutc'

The same remains unchanged, because everything in js is an object, and the function is also an object. For test, it is just a Function name, function reference, which points to this function. When foo = test, foo also points to this function.

What if you assign the object's method to a variable and then call the variable directly:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  }
}
var test = obj.foo;
test();
// Window

You can see that this executes the global at this time. When we put test = obj.foo, test directly points to a reference to a function. At this time, it actually has nothing to do with the object obj. Therefore, it is called directly as an ordinary function. Therefore, this points to the global object.

Some pitfalls

We often encounter some pitfalls in the callback function:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  },
  foo2: function() {
    console.log(this);
    setTimeout(this.foo, 1000);
  }
}
obj.foo2();

When we execute this code, we will find that this printed twice is different. :

The first time this is printed directly in foo2, which points to the object obj, we have no doubt;

But this.foo executed in setTimeout points to the global object, here Shouldn't you use it as a function method? This often confuses many beginners;
In fact, setTimeout is just a function, and the function must require parameters. We pass this.foo as a parameter to the setTimeout function, just like it requires a fun parameter. , when passing in parameters, we actually do the operation fun = this.foo. Did you see that? Here we directly point fun to the reference of this.foo; when executing, fun() is actually executed, so it has been combined with obj is irrelevant, it is called directly as an ordinary function, so this points to the global object.

This problem is commonly encountered in many asynchronous callback functions;

Solution

In order to solve this problem, we can use the characteristics of closures to deal with it:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  },
  foo2: function() {
    console.log(this);
    var _this = this;
    setTimeout(function() {
      console.log(this);  // Window
      console.log(_this);  // Object {name: "qiutc"}
    }, 1000);
  }
}
obj.foo2();

You can see that using this directly is still Window; because this in foo2 points to obj, we can first use a variable _this to store it, and then use _this in the callback function to point to the current one Object;

Another pitfall of setTimeout

As I said before, if the callback function is executed directly without a bound scope, then its this points to the global object (window ), will point to undefined in strict mode. However, the callback function in setTimeout behaves differently in strict mode:

'use strict';
function foo() {
  console.log(this);
}
setTimeout(foo, 1);
// window

It stands to reason that we have added strict mode, and the foo call does not specify this, so it should be It comes out undefined, but the global object still appears here. Is the strict mode invalid?

No, even in strict mode, when the setTimeout method calls the incoming function, if the function does not specify this, then it will do an implicit operation - automatically inject the global context , equivalent to calling foo.apply(window) instead of foo();

Of course, if we have specified this when passing in the function, then the global object will not be injected, such as: setTimeout(foo .bind(obj), 1);;

http://stackoverflow.com/questions/21957030/why-is-window-still-defined-in-this-strict-mode-code

Used as a constructor

In js, in order to implement a class, we need to define some constructors. When calling a constructor, we need to add the new keyword:

function Person(name) {
  this.name = name;
  console.log(this);
}
var p = new Person('qiutc');
// Person {name: "qiutc"}

我们可以看到当作构造函数调用时,this 指向了这个构造函数调用时候实例化出来的对象;

当然,构造函数其实也是一个函数,如果我们把它当作一个普通函数执行,这个 this 仍然执行全局:

function Person(name) {
  this.name = name;
  console.log(this);
}
var p = Person('qiutc');
// Window

其区别在于,如何调用函数(new)。

箭头函数

在 ES6 的新规范中,加入了箭头函数,它和普通函数最不一样的一点就是 this 的指向了,还记得在上文中(作为对象的方法调用-一些坑-解决)我们使用闭包来解决 this 的指向问题吗,如果用上了箭头函数就可以更完美的解决了:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  },
  foo2: function() {
    console.log(this);
    setTimeout(() => {
      console.log(this);  // Object {name: "qiutc"}
    }, 1000);
  }
}
obj.foo2();

可以看到,在 setTimeout 执行的函数中,本应该打印出在 Window,但是在这里 this 却指向了 obj,原因就在于,给 setTimeout 传入的函数(参数)是一个箭头函数:

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

根据例子我们理解一下这句话:
在 obj.foo2() 执行的时候,当前的 this 指向 obj;在执行 setTimeout 时候,我们先是定义了一个匿名的箭头函数,关键点就在这,箭头函数内的 this 执行定义时所在的对象,就是指向定义这个箭头函数时作用域内的 this,也就是 obj.foo2 中的 this,即 obj;所以在执行箭头函数的时候,它的 this -> obj.foo2 中的 this -> obj;

简单来说, 箭头函数中的 this 只和定义它时候的作用域的 this 有关,而与在哪里以及如何调用它无关,同时它的 this 指向是不可改变的。

call, apply, bind

在 js 中,函数也是对象,同样也有一些方法,这里我们介绍三个方法,他们可以更改函数中的 this 指向:

call

fun.call(thisArg[, arg1[, arg2[, ...]]])

它会立即执行函数,第一个参数是指定执行函数中 this 的上下文,后面的参数是执行函数需要传入的参数;

apply

fun.apply(thisArg[, [arg1, arg2, ...]])

它会立即执行函数,第一个参数是指定执行函数中 this 的上下文,第二个参数是一个数组,是传给执行函数的参数(与 call 的区别);

bind

var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);

它不会执行函数,而是返回一个新的函数,这个新的函数被指定了 this 的上下文,后面的参数是执行函数需要传入的参数;

这三个函数其实大同小异,总的目的就是去指定一个函数的上下文(this),我们以 call 函数为例;

为一个普通函数指定 this

var obj = {
  name: 'qiutc'
};
function foo() {
  console.log(this);
}
foo.call(obj);
// Object {name: "qiutc"}

可以看到,在执行 foo.call(obj) 的时候,函数内的 this 指向了 obj 这个对象,成功;

为对象中的方法指定一个 this

var obj = {
  name: 'qiutc',
  foo: function () {
    console.log(this);
  }
}
var obj2 = {
  name: 'tcqiu222222'
};
obj.foo.call(obj2);
// Object {name: "tcqiu222222"}

可以看到,执行函数的时候这里的 this 指向了 obj2,成功;

为构造函数指定 this

function Person(name) {
  this.name = name;
  console.log(this);
}
var obj = {
  name: 'qiutc2222222'
};
var p = new Person.call(obj, 'qiutc');
// Uncaught TypeError: Person.call is not a constructor(…)

这里报了个错,原因是我们去 new 了 Person.call 函数,而非 Person ,这里的函数不是一个构造函数;

换成 bind 试试:

function Person(name) {
  this.name = name;
  console.log(this);
}
var obj = {
  name: 'qiutc2222222'
};
var Person2 = Person.bind(obj);
var p = new Person2('qiutc');
// Person {name: "qiutc"}
console.log(obj);
// Object {name: "qiutc2222222"}

打印出来的是 Person 实例化出来的对象,而和 obj 没有关系,而 obj 也没有发生变化,说明,我们给 Person 指定 this 上下文并没有生效;

因此可以得出: 使用 bind 给一个构造函数指定 this,在 new 这个构造函数的时候,bind 函数所指定的 this 并不会生效;

当然 bind 不仅可以指定 this ,还能传入参数,我们来试试这个操作:

function Person(name) {
  this.name = name;
  console.log(this);
}
var obj = {
  name: 'qiutc2222222'
};
var Person2 = Person.bind(obj, 'qiutc111111');
var p = new Person2('qiutc');
// Person {name: "qiutc111111"}

可以看到,虽然指定 this 不起作用,但是传入参数还是起作用了;

为箭头函数指定 this

我们来定义一个全局下的箭头函数,因此这个箭头函数中的 this 必然会指向全局对象,如果用 call 方法改变 this 呢:

var afoo = (a) => {
  console.log(a);
  console.log(this);
}
afoo(1);
// 1
// Window
var obj = {
  name: 'qiutc'
};
afoo.call(obj, 2);
// 2
// Window

可以看到,这里的 call 指向 this 的操作并没有成功,所以可以得出: 箭头函数中的 this 在定义它的时候已经决定了(执行定义它的作用域中的 this),与如何调用以及在哪里调用它无关,包括 (call, apply, bind) 等操作都无法改变它的 this。

只要记住箭头函数大法好,不变的 this。

更多JavaScript 中的 this !相关文章请关注PHP中文网!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
JavaScript and the Web: Core Functionality and Use CasesJavaScript and the Web: Core Functionality and Use CasesApr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding the JavaScript Engine: Implementation DetailsUnderstanding the JavaScript Engine: Implementation DetailsApr 17, 2025 am 12:05 AM

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python vs. JavaScript: The Learning Curve and Ease of UsePython vs. JavaScript: The Learning Curve and Ease of UseApr 16, 2025 am 12:12 AM

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python vs. JavaScript: Community, Libraries, and ResourcesPython vs. JavaScript: Community, Libraries, and ResourcesApr 15, 2025 am 12:16 AM

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

From C/C   to JavaScript: How It All WorksFrom C/C to JavaScript: How It All WorksApr 14, 2025 am 12:05 AM

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

JavaScript Engines: Comparing ImplementationsJavaScript Engines: Comparing ImplementationsApr 13, 2025 am 12:05 AM

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Beyond the Browser: JavaScript in the Real WorldBeyond the Browser: JavaScript in the Real WorldApr 12, 2025 am 12:06 AM

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.

Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Apr 11, 2025 am 08:23 AM

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Have Crossplay?
1 months agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Atom editor mac version download

Atom editor mac version download

The most popular open source editor