Home  >  Article  >  Web Front-end  >  Detailed explanation of the usage and differences of this, call and apply in JavaScript

Detailed explanation of the usage and differences of this, call and apply in JavaScript

PHPz
PHPzOriginal
2016-05-16 15:17:091291browse

In my previous JavaScript learning, this, call, and apply always confused me, but they are widely used. So I spent a whole day to understand JavaScript's this, call, and apply.

There are also many books that I referenced along the way, mainly "JavaScript Design Patterns and Development Practices", supplemented by "JavaScript Advanced Programming" and "JavaScript You Don't Know". These three books have been of great help to me in understanding this, call, and apply.

First, let’s talk about this.

In the description of this in "JavaScript Design Patterns and Development Practices", I think there is a sentence that hits the core point of this. That is:

This in JavaScript always points to an object
In practical applications, the pointing of this can be divided into the following four types:

  1. As Object method calls

  2. as ordinary function calls

  3. Constructor calls

  4. apply and call Calling

Next we will analyze the first three points. As for the apply and call in the fourth point, we will explain it in detail in the call and apply section.

1. Calling as an object method

Explanation: When calling as an object method, this points to the object.
Example:

/**
 * 1.作为对象的方法调用
 *
 * 作为对象方法调用时,this指向该对象。
 */

var obj = {
 a: 1,
 getA: function() {
  console.log(this === obj);
  console.log(this.a);
 }
};

obj.getA(); // true , 1

2. Called as an ordinary function

Note: When called as an ordinary function, this always points to Global object (window in browsers).
Example:

/**
 * 2.作为普通函数调用
 *
 * 不作为对象属性调用时,this必须指向一个对象。那就是全局对象。
 */

window.name = 'globalName';

var getName = function() {
 console.log(this.name);
};

getName(); // 'globalName'

var myObject = {
 name: "ObjectName",
 getName: function() {
  console.log(this.name)
 }
};

myObject.getName(); // 'ObjectName'

// 这里实质上是把function() {console.log(this.name)}
// 这句话赋值给了theName。thisName在全局对象中调用,自然读取的是全局对象的name值
var theName = myObject.getName;

theName(); // 'globalName'

3. Constructor call

Explanation: When called as a constructor, this points to the returned one object.
Example:

/**
 * 3.作为构造器调用
 * 
 * 作为构造器调用时,this指向返回的这个对象。
 */

var myClass = function() {
 this.name = "Lxxyx";
};

var obj = new myClass();

console.log(obj.name); // Lxxyx
console.log(obj) // myClass {name: "Lxxyx"}

But if return other objects are manually specified in the constructor, then this will not work.
If the returned data type is another data type, there is no problem.

var myClass = function() {
 this.name = "Lxxyx";
 // 加入return时,则返回的是别的对象。this不起作用。
 return {
  name:"ReturnOthers"
 }
};

var obj = new myClass();
console.log(obj.name); // ReturnOthers

4. Call and Apply

Call and Apply have the same purpose. They are all used to specify the pointer of this in the function body.

The difference between Call and Apply

Call: The first parameter is the pointer to this, and the parameters to be passed to the function must be input one by one.
Apply: The first parameter is the pointer to this, the second parameter is an array, and all parameters are passed in at once.

If the first parameter is null, this points to the call itself.

1. Change this to point to

Explanation: This is the most common use of call and apply. Used to change the pointer of this in the function body.
Example:

var name = "GlobalName"

var func = function() {
 console.log(this.name)
};

func(); // "GlobalName"

var obj = {
 name: "Lxxyx",
 getName: function() {
  console.log(this.name)
 }
};

obj.getName.apply(window) // "GlobalName" 将this指向window
func.apply(obj) // "Lxxyx" 将this指向obj

2. Borrow methods from other objects

Here, we start with an immediately executed anonymous function:

(function(a, b) {
 console.log(arguments) // 1,2
 // 调用Array的原型方法
 Array.prototype.push.call(arguments, 3);
 console.log(arguments) // 1,2,3
})(1,2)

The function has arguments attribute, and arguments is an array-like array.
But arguments cannot directly call the array method, so we have to use call or apply to call the prototype method of the Array object.
The principle is also easy to understand. For example, what you just called is the push method, and the push method is in Google's v8 engine. The source code is like this:

function ArrayPush() {
 var n = TO_UINT32(this.length); // 被push对象的长度
 var m = % _ArgumentsLength(); // push的参数个数
 for (var i = 0; i < m; i++) {
  this[i + n] = % _Arguments(i); // 复制元素
 }
 this.length = n + m; //修正length属性
 return this.length;
}

It only It is related to this, so as long as it is an array-like object, you can call related methods to process it.

This part of the content is quite complicated, and I am not very good at it either. Therefore, I recommend qualified students to buy relevant books, or wait for my follow-up blog articles.

Impressions

By studying this part, I have deepened my understanding of JavaScript. The most intuitive manifestation is that when looking at the source code of some excellent frameworks, you are no longer confused by this, call, apply, and bind. Still very happy~

In the next period of time, I am going to explore in depth the CSS I learn and use daily. After all, after learning JavaScript, HTML and CSS cannot be left behind.

【Recommended related tutorials】

1. JavaScript video tutorial
2. JavaScript online manual
3. bootstrap tutorial

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