Home > Web Front-end > JS Tutorial > body text

In-depth understanding of this pointer in javascript

小云云
Release: 2018-03-17 16:21:10
Original
1574 people have browsed it

This article mainly shares with you an in-depth understanding of the this pointer in javascript. When writing java, if this is used incorrectly, idea will directly report an error!

For example...



In object-oriented programming, there are two Important concepts: One is a class and the other is an instantiated object. A class is an abstract concept. To use a vivid metaphor, a class is like a mold, and the instantiated object is through this mold. For manufactured products, instantiated objects are the real things we need. Classes and instantiated objects are closely related, but the functions of classes cannot replace instantiated objects when using them, just like molds and molds. The relationship between the manufactured products and the uses of the two are different.

We can see from the above code that the this pointer can only be used in instantiated objects in the Java language. The this pointer is equal to the instantiated object, and the dot operator is added after this. The thing after the operator is what this has, such as: name, job, hands, feet, etc.

In factThe logical concept of this pointer in javascript is also an instantiated object. This is consistent with the this pointer in the java language, but the this pointer in javascript is smaller than the this pointer in java. This is much difficult to understand. I personally think there are three fundamental reasons:

Reason 1: Javascript is a functional programming language. The strange thing is that it also has this pointer, which shows that this is functional programming. The language is also an object-oriented language. To be more specific, the function in JavaScript is a higher-order function. The higher-order function in the programming language can be passed as an object. At the same time, the function in JavaScript can also be used as a constructor. This construct Functions can create instantiated objects. As a result, the pointer of this pointer will continue to change when the method is executed, which is difficult to control.

Reason 2: The global scope in JavaScript has a great impact on the this pointer. From the above Java example, we can see that the this pointer can only be changed after using the new operator. It takes effect, but this in JavaScript will also take effect without performing new operation. At this time, this will often point to the global object window.

Reason 3: The call and apply operators in JavaScript can change the this pointer at will. This seems very flexible, but this unreasonable approach destroys our understanding of the original meaning of this pointer, and also makes it difficult to write code. It is difficult to understand what this really points to



##The above three reasons all violate the traditional use of this pointer Methods, they all have different understandings from the traditional this principle, and in actual development, the three reasons are often intertwined, so, this, it is all in the clouds...


Introductory book: professional Javascript for web devolopers, - the advanced version is this:

this always points to the calling method Object!



##var name="zhoulujun";

function say(){

console.log(this.name)

}

say(); //zhoulujun



##In the script tag we can

use this pointer directly , this pointer (pointing to the window object, result) is the window object , they are equal even if the triple equal sign is used. The global scope often interferes with our understanding of the characteristics of the JavaScript language. The essence of this interference is:

In the JavaScript language

the global scope can be understood as the window object, remember Window is an object rather than a class, which means window is an instantiated object. This instantiation process is completed by the JavaScript engine when the page is loaded. The elements in the entire page are condensed into this window object, because programmers cannot control and operate this instantiation process through programming languages, so we do not have the feeling to construct this pointer during development, and often ignore it. This interferes with our understanding of the fact that this pointer points to window in the code. situation.

Here this points to the window object, so this.name->zhoulujun!



##When executing the say function, JavaScript will create an Execute context (execution context), which contains all the information needed during the runtime of the say function. Execute context also has its own Scope chain. When the function runs, the JavaScript engine will first initialize the execution context's scope chain from the scope chain using the say function.

Here you can roughly remember:

var myObj={
name:"zhoulujun",
fn:function(){
console.log(this.name)
}
};
myObj.fn();
Copy after login


这里的this指向obj,因为fn()运行在obj里面……

然后再来看……

var name="zhoulujun";
function say(){
console.log(this.name)
console.log(this)
}
say();
function say2(){
var site="zhoulujun.cn";
console.log(this.site);
}
say2();
Copy after login


myObj2={
site:"zhoulujun.cn",
fn:function(){
console.log(this.site)
}
}
Copy after login



这里的this指向的是对象myObj2,因为你调用这个fn是通过myObj2.fn()执行的,那自然指向就是对象myObj2,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个

然后,我们更深入(受不了 …………

myObj3={
site:"zhoulujun.cn",
andy:{
site:"www.zhoulujun.cn",
fn:function(){
console.log(this.site)
}
}
};
myObj3.andy.fn();
Copy after login



这里同样也是对象Object点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。

如果,你实在理解不了,就这么样背下来吧!

情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,如果不相信,那么接下来我们继续看几个例子。

这样既对了吗??深入点(就受不了了……讨厌……

myObj3={
site:"zhoulujun.cn",
andy:{
site:"www.zhoulujun.cn",
fn:function(){
console.log(this)
console.log(this.site)
}
}
};
//    myObj3.andy.fn();
var fn=myObj3.andy.fn;
fn();
Copy after login



其实,这里的 fn等价于

fn:function(age){

console.log(this.name+age);

}

下面我们来聊聊函数的定义方式:声明函数和函数表达式

我们最上面第一个案例定义函数的方式在javascript语言称作声明函数,第二种定义函数的方式叫做函数表达式,这两种方式我们通常认为是等价的,但是它们其实是有区别的,而这个区别常常会让我们混淆this指针的使用,我们再看看下面的代码:



Why can say be executed but say3 cannot? That’s because:



Why the print result of say3 is undefined, I mentioned in the previous article that undefined is The stack area of ​​the memory already has the name of the variable, but there is no variable value in the stack area. At the same time, there is no specific object in the heap area. This is caused by the JavaScript engine scanning variable definitions during preloading, but the printing result of ftn01 is very Surprisingly, since the completed function definition is printed out, and the code is not executed in order, this can only explain one problem:

In the JavaScript language, functions are defined by declaring functions, and the JavaScript engine is in the preprocessing process The function definition and assignment operations have been completed here. Here I will add the characteristics of preprocessing in JavaScript. In fact, preprocessing is related to the execution environment. In the previous article, I mentioned that there are two major categories of execution environments: global execution environment and local execution environment. The execution environment is reflected through context variables. In fact, this process is completed before the function is executed. Preprocessing is another way of constructing the execution environment. In short, the main purpose of preprocessing and constructing the execution environment is to clarify the variables. Definition, distinguish the boundaries of variables, but there are some differences for declaring functions during global scope construction or global variable preprocessing. Declaring functions will complete variable definition and assignment operations at the same time, so we see the running results of the above code. Since the declared functions are completed during the global scope construction, the declared functions are all attributes of the window object. This explains why no matter where we declare the function, the declared function ultimately belongs to the window object.

It is recommended to take a look here - the execution sequence of a Java class:

http://www.zhoulujun.cn/zhoulujun/html/java/javaBase/7704.html



其实在javascript语言里任何匿名函数都是属于window对象,它们也都是在全局作用域构造时候完成定义和赋值,但是匿名函数是没有名字的函数变量,但是在定义匿名函数时候它会返回自己的内存地址,如果此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了,因为匿名函数也是在全局执行环境构造时候定义和赋值,所以匿名函数的this指向也是window对象,所以上面代码执行时候fn的this都是指向window,因为javascript变量名称不管在那个作用域有效,堆区的存储的函数都是在全局执行环境时候就被固定下来了,变量的名字只是一个指代而已。

类似的情况(面试题喜欢这么考!)……比如:



this都是指向实例化对象,前面讲到那么多情况this都指向window,就是因为这些时候只做了一次实例化操作,而这个实例化都是在实例化window对象,所以this都是指向window。我们要把this从window变成别的对象,就得要让function被实例化,那如何让javascript的function实例化呢?答案就是使用new操作符。

再来看 构造函数:

function  User(){
this.name="zhoulujun";
console.log(this);
}
var andy=new User();
console.log(andy.name)
Copy after login



why andy 的name 是 zhoulujun,那是:因为:

new关键字可以改变this的指向,将这个this指向对象andy,

那andy什么时候又成了思密达,oh,no,is Object?

Because the new keyword is used to create an object instance(Read important things silently three times)

We use the variable andy to create a User user instance (equivalent to copying A copy of User into the object andy). At this time, it is only created and not executed. The object that calls this function User is the object andy, so naturally this points to the object andy. So why is there a name in the object User? Because you have already A copy of the User function is copied into the object andy. Using the new keyword is equivalent to copying a copy.

java Programmer: Class user=new User(); looks familiar...



##function is both a function and an object. When function is a function, it can also be used as a constructor. The constructor of javascript is mine It is often thought that classes and constructors are combined into one. Of course there is no concept of class in the JavaScript language specification, but my understanding can be used as a constructor and an ordinary function. A difference, it will be easier to understand.

Below I post the explanation of the new operator in "Javascript Advanced Programming":

The new operator will cause the following changes to the constructor:

1. Create a new object;

2. Assign the scope of the constructor to the new object (so this points to the new object);

3. Execute the code in the constructor (add attributes to this new object);

4. 返回新对象

……

妈的:读的那么拗口,不明觉厉…………看图……还不

不明白……

var myObj5={
name:"andy"
};
var myObj6=new Object();
myObj6.name="andy";
function  say5(name){
console.log(name)
}
var say6=new Function("name","console.log(name)");
console.log(myObj5)
console.log(myObj6)
say5("andy");
say6("andy");
Copy after login



还不明白,就请奶奶买块豆腐,撞死算了……

第四点也要着重讲下,记住构造函数被new操作,要让new正常作用最好不能在构造函数里写return,没有return的构造函数都是按上面四点执行,有了return情况就复杂了

return这王八蛋……



那么我这样呢……



does it have to be like this?Tell me why(why),is there something I have missed?

Tell me why(why),cos I don't understand…………



那是因为……because of u?no return……



所以:如果返回的是基本类型,就会丢掉…只能返回Object类型……typeof xx ===“object”

看到called 没有?什么鬼!!

其实new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

var a={
name:"andy",
site:"zhoulujun.cn",
fn:function(age){
console.log(this.name+age);
}
};
var b={
name:"zhoulujun",
site:"www.zhoulujun.cn",
fn:function(age){
console.log(this.name+age);
}
};
a.fn(2); //andy2
a.fn.call(b,2) //zhoulujun2
a.fn.apply(b,[2])//zhoulujun2
当然,还有bind……
var arr = [1, 2];
var add = Array.prototype.push.bind(arr, 3);
// effectively the same as arr.push(3)
add();
// effectively the same as arr.push(3, 4)
add(4);
console.log(arr);
// <- [1, 2, 3, 3, 4]
在下面的例子,this将无法在作用域链中保持不变。这是规则的缺陷,并且常常会给业余开发者带来困惑。
function scoping () {
console.log(this);
return function () {
console.log(this);
};
}
scoping()();
// <- Window
// <- Window
有一个常见的方法,创建一个局部变量保持对this的引用,并且在子作用域中不能有同命变量。子作用域中的同名变量将覆盖父作用域中对this的引用。
function retaining () {
var self = this;
return function () {
console.log(self);
};
}
retaining()();
// <- Window
除非你真的想同时使用父作用域的this,以及当前this值,由于某些莫名其妙的原因,我更喜欢是使用的方法.bind函数。这可以用来将父作用域的this指定给子作用域。
function bound () {
return function () {
console.log(this);
}.bind(this);
}
bound()();
// <- Window
Copy after login

写到这里,都看不下去,逻辑有点混乱,有的是从前辈哪里引用的。

改天有时间整理下,然后,在去讲下闭包(……closer





The above is the detailed content of In-depth understanding of this pointer in javascript. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template