当函数被调用执行时,变量对象会生成,这个时候,this的指向就会确定。如果当前的执行上下文处于函数调用栈的栈顶,那么这个时候变量对象会变成活动的对象,同时this的指向确认。也正因为如此,导致同一个函数内部的this到底是指向谁是非常灵活且不确定的。在此,我们只需要牢记: 当前函数的this是在函数被调用执行的时候才确定的。

this的使用主要在三方面

(1)全局对象中的this。

//通过this绑定到全局变量
this.a1 = 10;//通过声明绑定到变量对象,但在全局环境中,变量对象就是它本身
var a2 = 20;//仅仅只有赋值操作,标识符会隐士绑定到全局对象
a3 = 30;//输出结果全部符合预期
console.log(a1);
console.log(a2);
console.log(a3);

(2)函数中的this。

在一个函数的执行上下文中,this由该函数的调用者提供,由调用函数的方式来决定其指向

function fn(){console.log(this);
}
fn();    //fn为调用者

如果调用者被一个对象所拥有,那么在函数内部使用严格函数时,内部的this指向该对象。如果调用者函数独立调用,那么该函数内部的this则指向undefined。非严格模式下,当this指向undefined时,它会自动指向全局对象。

function fn(){'use strict'    //使用严格模式console.log(this);
}fn();            //fn是调用者,独立调用,this为undefined
window.fn();     //fn是调用者,被window对象所拥有,this为window对象

demo1:

var a =20;
var obj = { a = 40; };
function fn(){console.log('fn this:', this);console.log('fn this.a:', this.a);function foo(){console.log('foo this.a:', this.a);    }foo();
}fn.call(obj);
//输出结果为:
//fn this:Object{a:40}
//40
//20
fn();
//输出结果为:
//fn this:Window{}
//20
//20       

该例中无论fn的调用方式在怎样变化,foo一直都是独立调用,因此foo内部的this都是指向undefined的,由于是非严格模式,因此自动指向window。

demo2:

'use strict'
var a=20;
function foo(){var a=1;var obj={a:10,c:this.a+20}return obj.c;
}
console.log(window.foo());    //40,window对象调用则this指向window的a
console.log(foo());           //Uncaught TypeError:....,独立调用this指向undefined

对象字面量的写法不会产生自己的作用域,因此obj.c上的this属性并不会指向obj,而是与foo函数内部的this一样。因此当使用window.foo()调用时,foo内部的this指向window对象,这个时候this.a能访问到全局变量a。foo独立调用时,foo函数内部的this指向undefined,由于在严格模式下,所以代码报错a是undefined。

demo3:牢记调用者的独立调用与被某个对象所拥有的区别。

var a = 20;
var foo = {a:10,getA:function(){return this.a;   }
}
console.log(foo.getA());    //10  getA为调用者,被foo所拥有,getA执行时this指向foovar test = foo.getA;
console.log(test());    //20    test为调用者,是独立调用,this指向undefined。

foo.getA()中,getA为调用者,被foo所有,当getA执行时,this指向foo,因此返回10;

而test执行时,test为调用者,它是独立调用。虽然test与foo.getA的引用都是指向同一个函数,但是调用方式的不同导致getA内部的this指向了undefined,自动转向window,所以返回20。

两个思考题:

Q1:
function foo(){console.log(this.a);
}
function active(fn){fn();
}
var a=20;
var obj = {a:10,getA:foo,active:active
}active(obj.getA);    //返回的值为多少
obj.active(obj.getA)    //返回值为多少Q2:
var n = 'window';
var obj = {n:'obj',getN:function(){return function(){return this.n;            }}
}console.log(obj.getN()());    //返回值为多少

(3)call/apply/bind显式指定this。

JavaScript内部提供了一种可以手动设置函数内部this指向的方式,他们就是call/apply/bind。

call函数的第一个参数是为函数内部指定this指向,后续的参数则是函数执行时所需要的参数,一个个传递。apply第一个参数与call相同,为函数内部指定this指向,而函数的参数,则以数组的形式传递,作为apply的第二个参数。

function fn(num1.num2){return this.a + num1 + num2;
}var a = 20;
var obj = { a:40 };//正常执行
fn(10,10);    //40//通过call改变this指向
fn.call(obj,10,10);    //60//通过apply改变this指向
fn.apply(obj,[10,10]);    //60

当调用call/apply函数时,函数内部this被显式指定,并且函数会立即执行。而当函数调用bind时,函数不会立即执行,而是返回一个新的函数,这个新的函数与原函数有共同的函数体,但它并非原函数,并且新函数的参数与this指向都已被确定,参数为bind的后续参数。

function fn(num1,num2){return this.a + num1 + num2;
}var a=20;
var obj = {a:40;
}var _fn = fn.bind(obj,1,2);console.log(_fn === fn);    //false 说明不是两函数不相等
_fn();    //43
_fn(1,4);    //43,因为参数被绑定,因此重新传入参数是无效的

call/apply/bind的特张可以用于将类数组化为数据,实现继承、封装等操作。

                                                                                                                    参考:《JavaScript核心技术开发解密》 阳波 编著

javascript学习系列(四)JS中this的使用相关推荐

  1. javascript学习系列(23):数组中的解构方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  2. javascript学习系列(25):数组中的substr

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  3. javascript学习系列(24):数组中的substring方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  4. javascript学习系列(21):数组中的reduceRight法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  5. javascript学习系列(22):数组中的reduceRight法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  6. javascript学习系列(20):数组中的bind,apply,call

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  7. javascript学习系列(19):数组中的Array.from方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  8. javascript学习系列(18):数组中的include方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  9. javascript学习系列(17):数组中的find方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  10. javascript学习系列(16):数组中的every方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

最新文章

  1. L09-10老男孩Linux运维实战培训-Nginx服务生产实战应用指南05(架构解决方案)
  2. Could not load file or assembly 'System.Web.Extensions
  3. 【网页设计】框架的高度随框架里面的内容的多少而改变——转
  4. 第十章—DOM(0)—NODE类型
  5. 010_SpringBoot视图层技术thymeleaf-变量输出与字符串操作
  6. 波卡链Substrate (3)SRML框架
  7. mpvue 微信小程序 Image 图片实现宽度100%,高度自适应
  8. openlayers4 入门开发系列之地图工具栏篇(附源码下载)
  9. 洛谷 P3378 【模板】堆
  10. Golang 变量申明方式
  11. 树莓派安装python3.8_在树莓派(Raspberry Pi)上编译安装更新版本的Python
  12. 简单构建一个xmlhttp对象池合理创建和使用xmlhttp对象
  13. javascript 组成
  14. EVC下如何直接访问寄存器?
  15. Kali Linux 2017.3 安装网易云音乐
  16. js 通过图片URL地址将图片转为可操作的File文件对象
  17. 风险管理计划包括哪些内容
  18. 虚拟机win7装oracle,大神教你win7系统安装Oracle VM VirtualBox虚拟机的处理教程
  19. 标志logo设计/欣赏
  20. 如何看懂k线图:K线详细分析图解

热门文章

  1. [Java教程]3.第一个Java程序
  2. 解决ts运行报错 : 无法加载文件 C:\Users\XXX\AppData\Roaming\npm\webpack.ps1因为在此系统上禁止运行脚本
  3. 用C语言编写购买地铁车票的规定如下:乘1-4站,3元/位;乘5-9站,4元/位;乘9站以上,5元/位,编写一个程序,利用循环结构、选择结构实现:(1) 输入人数、站数,输出应付款;(2)当
  4. 名画221 陈继儒《书画合册十二开》
  5. 第七篇:爬虫实战--- 1、破解滑动验证码
  6. Delphi 同时支持Windows、Linux、OS X、iOS、Android的新一代跨平台编程语言开发工具
  7. 2022年游戏蓝牙耳机排行榜:四款口碑最好的游戏蓝牙耳机
  8. codeforces1549 C. Web of Lies
  9. 初识javaScript(三)
  10. 在其他条件不变的前提下,以下哪种做法容易引起机器学习中的过拟合问题()