博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
再次讨论javascript 中的this
阅读量:6479 次
发布时间:2019-06-23

本文共 6145 字,大约阅读时间需要 20 分钟。

原文: 

核心总结:

1.不论函数在哪里被调用,只要没有指定调用方,则this都指向window。指定了调用方,就指向调用方。(参考:

2.作为构造函数中调用,this指向新生成的对象。

分析一下:setTimeout和setInterval

bind的作用就是给函数一个指定的thisArg,经常使用bind的地方就是setTimeout和setInterval了。为什么呢?

setTimeout和setInterval都有一个特点,它会将回调函数的作用域转移到window上面。其实结合我们上面说的,很容易知道为什么。
以setTimeout为例:翻看,可以发现,setTimeout是把一段callback代码延迟执行。写过callback的同学都知道,callback的代码其实就是占了位,然后去调用一行行的代码,所以,callback中的this也会指向window。
实际开发中,我们不希望this指向window,故而常使用bind来使this指向我们希望的对象。

----------------------------------------------------------------------------------------------------------------------------------------------------------------

ad

这篇文章很好: 

前些天在练习写一个小例子的时候用到了定时器,发现在setInterval和setTimeout中传入函数时,函数中的this会指向window对象,如下例:

var num = 0;function Obj (){    this.num = 1,    this.getNum = function(){        console.log(this.num);    },    this.getNumLater = function(){        setTimeout(function(){            console.log(this.num);        }, 1000)    }}var obj = new Obj; obj.getNum();//1  打印的是obj.num,值为1obj.getNumLater()//0  打印的是window.num,值为0

从上述例子中可以看到setTimeout中函数内的this是指向了window对象,这是由于setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致这些代码中包含的 this 关键字会指向 window (或全局)对象。详细可参考

 

若想要让setTimeout中的this指向正确的值,可以使用以下三种比较常用的方法来使this指向正确的值:

1.将当前对象的this存为一个变量,定时器内的函数利用闭包来访问这个变量,如下:

var num = 0;function Obj (){    var that = this;    //将this存为一个变量,此时的this指向obj    this.num = 1,    this.getNum = function(){        console.log(this.num);    },    this.getNumLater = function(){        setTimeout(function(){            console.log(that.num);    //利用闭包访问that,that是一个指向obj的指针        }, 1000)    }}var obj = new Obj; obj.getNum();//1  打印的是obj.num,值为1obj.getNumLater()//1  打印的是obj.num,值为1

 

这种方法是将当前对象的引用放在一个变量里,定时器内部的函数来访问到这个变量,自然就可以得到当前的对象。

2.利用bind()方法

var num = 0;function Obj (){    this.num = 1,    this.getNum = function(){        console.log(this.num);    },    this.getNumLater = function(){        setTimeout(function(){            console.log(this.num);        }.bind(this), 1000)    //利用bind()将this绑定到这个函数上    }}var obj = new Obj; obj.getNum();//1  打印的为obj.num,值为1obj.getNumLater()//1  打印的为obj.num,值为1

 

bind()方法是在Function.prototype上的一个方法,当被绑定函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this。在这个例子中,在调用setTimeout中的函数时,bind方法创建了一个新的函数,并将this传进新的函数,执行的结果也就是正确的了。关于bind方法可参考 

3. 箭头函数

 

var num = 0;function Obj (){    this.num = 1,    this.getNum = function(){        console.log(this.num);    },    this.getNumLater = function(){        setTimeout(() => {            console.log(this.num);        }, 1000)    //箭头函数中的this总是指向外层调用者,也就是Obj    }}var obj = new Obj; obj.getNum();//1  打印的是obj.num,值为1obj.getNumLater()//1  打印的是obj.num,值为1

 

ES6中的箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj,因此利用箭头函数就可以轻松解决这个问题。

以上三种方法都是比较常用的,当然如果使用call或apply方法来代替bind方法,得到的结果也是正确的,但是call方法会在调用之后立即执行,那样也就没有了延时的效果,定时器也就没有用了,所以推荐使用上述方法来将this传进setTimeout和setInterval中。 

 

在JavaScript中,this 的概念比较复杂。在面向对象编程中,this 还是随处可用的。这篇文章介绍了javascript中的this相关知识,对javascript this相关知识感兴趣的朋友一起学习吧

------------------------------------------------------------------------------------------

JavaScript 是一种脚本语言,因此被很多人认为是简单易学的。然而情况恰恰相反,JavaScript 支持函数式编程、闭包、基于原型的继承等高级功能。本文仅采撷其中的一例:JavaScript 中的 this 关键字,深入浅出的分析其在不同情况下的含义,形成这种情况的原因以及 Dojo 等 JavaScript 工具中提供的绑定 this 的方法。可以这样说,正确掌握了 JavaScript 中的 this 关键字,才算迈入了 JavaScript 这门语言的门槛。

 至于js中this这个东西,好多淫解释过了,看起来好高端的样子,不晓得你看懂了木有?

先引用比较高端的,脚本之家里 的, 

好了,下面加上鄙人比较挫的解释

论点: this 不是变量,不是属性,不能为其赋值,它始终指向调用它的对象

感觉还TM太虚了,只要记住最重要的一条即可 ”它始终指向调用它的对象“ ,所以找到调用this的对象,就知道this到底指向谁了

1、

1
alert(
this
);

瞅瞅,弹出来的是么子,要么是”object window“ ,要么 "object" 总之就对象了,是那个对象呢?

1
alert(
this
=== window);

结果为'true' 所以了,现在调用它的对象是window了

2、

1
2
3
4
var
test =
function
(){
  
alert(
this
);
}
test();

猜猜上面弹出什么,是不是和"alert(this)" 这句一样的

1
2
3
4
var
test =
function
(){
  
alert(
this
=== window);
 
}
test();

运行上面的代码,是不是弹出了'true' ?

事情就这样完了?

要这么简单的话,何必那么多人都去论述这个鸟了?

3、

再来

1
2
3
4
var
test =
function
(){
  
alert(
this
=== window);
 
}
new
test();

哎哎,这次咋成'false'呢?

记住”this 始终指向调用它的对象“,第”1、“处调用该段代码的直接对象是全局对象,即"window" ;第”2、“处虽然是函数,但是调用其的仍然是”window“(不要弄混了,函数虽然是对象,但是调用它的是另一个对象);第”3、“处,使用了”new“ 这时其实已经发生变化了,这是一个构造函数,构造函数创建时创建了一个新的空的对象,即”new test()“创建了一个新的对象,然后再由这个对象指向函数"test"中的代码,因此此时this不在是window对象,而是该构造函数创建的新对象。

4、

1
2
3
4
5
6
7
var
test ={
  
'a'
:1,
  
'b'
:
function
(){
   
alert(
this
=== test)
  
}
 
}
test.b();

有了上面的论点,这下一下子清楚了吧!

5、

1
2
3
4
5
6
7
8
var
test ={
  
'a'
:1,
  
'b'
:
function
(){
   
alert(
this
=== test)
  
}
 
}
var
test1 = test;
test1.b();

so, 你不会认为结果为"false"吧,错了,虽然'test1'的值为'test'  但是'test1'不还是'test'对象么,它有新产生对象,你暂且理解为引用的了,两个都指向一个对象,奉上下面一段代码为证

1
2
3
4
5
6
7
8
9
var
test ={
  
'a'
:1,
  
'b'
:
function
(){
   
alert(
this
=== test)
  
}
 
}
var
test1 = test;
test.a = 2;
alert(test1.a);

如果弹出了”1“,你来骂我

6、再整个复杂的

1
2
3
4
5
6
7
8
9
var
test ={
  
'a'
:1,
  
'b'
:{
   
'b1'
:
function
(){
    
alert(
this
=== test);
   
}
  
}
 
}
test.b.b1();

这是"true"还是"false"呢?

按照上面的理论,这时"this"不再直接被'test'调用了,而是被'test.b' 调用, 奉上下面一段代码为证

1
2
3
4
5
6
7
8
9
var
test ={
  
'a'
:1,
  
'b'
:{
   
'b1'
:
function
(){
    
alert(
this
=== test.b);
   
}
  
}
 
}
test.b.b1();

 7、好再整个复杂点的

1
2
3
4
5
6
7
var
test =
function
(){
  
var
innerTest =
function
(){
   
alert(
this
=== test);
  
}
  
innerTest();
 
}
test();

你不会认为弹出"true"吧,不是按照上面的理论'innerTest'是被'test'调用的,然后'this'就指向'test'吗?

额,错就错在是谁调用的'innerTest', 其实这种函数都是'window'对象调用的,及时你嵌套一千层,调用各个函数的都是'window'对象,奉上下面这段代码为证

1
2
3
4
5
6
7
8
9
10
11
var
test =
function
(){
  
var
innerTest =
function
(){
   
alert(
this
=== window);
   
var
innerTest1 =
function
(){
    
alert(
this
=== window);
   
}
   
innerTest1();
  
}
  
innerTest();
 
}
test();

8、再来一段特殊的

1
2
3
4
5
6
var
test =
function
(){
  
alert(
this
=== window);
 
}
var
test1 = {
}
test.apply(test1);

这个我觉得大家都不会猜错,该函数的作用就是”调用一个对象的一个方法,以另一个对象替换当前对象“ 所以了'window' 对象已经被替代为'test1',自然为'false'了,奉上如下代码以为证明

1
2
3
4
5
6
var
test =
function
(){
  
alert(
this
=== test1);
 
}
 
var
test1 = {
  
}
test.apply(test1);

 那么诸如'call'之类的也就相似了

9、再来一个原型的继承,区别于字面量的继承

1
2
3
4
5
6
7
8
9
10
11
var
test =
function
(){
 
}
 
var
my =
function
(){
  
this
.a =
function
(){
   
alert(
this
=== mytest2);
  
}
 
}
 
var
mytest =
new
my();
 
test.prototype = mytest;
 
var
mytest2 =
new
test();
 
mytest2.a();

10、还剩下些什么了,可能就是'dom'对象了

1
2
3
4
5
6
7
<script>
  
var
mytest =
function
(context){
   
alert(context.getAttribute(
'id'
));
   
alert(
this
=== window);
  
}
 
</script>
 
<div id=
"test"
onclick=
"mytest(this)"
>aaaa</div>

看了上面的应该了解了吧,里面的'this'分别代表神马

转载地址:http://vwwuo.baihongyu.com/

你可能感兴趣的文章
学习iOS【3】数组、词典和集合
查看>>
Hessian 原理分析--转
查看>>
转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端
查看>>
easyui传入map的数据前台展示出tree格式数据
查看>>
悲观的思考,乐观的生活.我们既需要思考的深度,也需要生活的温度!
查看>>
java.math.BigDecimal
查看>>
Vitamio中文API文档(4)—— VitamioInstaller
查看>>
yii框架常用url地址
查看>>
python3.4学习笔记(十六) windows下面安装easy_install和pip教程
查看>>
MyGUI 解析
查看>>
Linux中的ls命令详细使用
查看>>
graph-tool文档(一)- 快速开始使用Graph-tool - 2.属性映射、图的IO和Price网络
查看>>
easyui treegrid逐步加载
查看>>
GraphicsLab Project之辉光(Glare,Glow)效果 【转】
查看>>
<转>Python: __init__.py 用法
查看>>
Linux Curl命令
查看>>
046 SparlSQL中的函数
查看>>
-27979 LoadRunner 错误27979 找不到请求表单 Action.c(73): Error -27979: Requested form not found...
查看>>
[LeetCode] Minimum Depth of Binary Tree
查看>>
,net运行框架
查看>>