javascript学习系列(四)JS中this的使用
当函数被调用执行时,变量对象会生成,这个时候,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的使用相关推荐
- javascript学习系列(23):数组中的解构方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(25):数组中的substr
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(24):数组中的substring方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(21):数组中的reduceRight法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(22):数组中的reduceRight法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(20):数组中的bind,apply,call
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(19):数组中的Array.from方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(18):数组中的include方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(17):数组中的find方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
- javascript学习系列(16):数组中的every方法
最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...
最新文章
- L09-10老男孩Linux运维实战培训-Nginx服务生产实战应用指南05(架构解决方案)
- Could not load file or assembly 'System.Web.Extensions
- 【网页设计】框架的高度随框架里面的内容的多少而改变——转
- 第十章—DOM(0)—NODE类型
- 010_SpringBoot视图层技术thymeleaf-变量输出与字符串操作
- 波卡链Substrate (3)SRML框架
- mpvue 微信小程序 Image 图片实现宽度100%,高度自适应
- openlayers4 入门开发系列之地图工具栏篇(附源码下载)
- 洛谷 P3378 【模板】堆
- Golang 变量申明方式
- 树莓派安装python3.8_在树莓派(Raspberry Pi)上编译安装更新版本的Python
- 简单构建一个xmlhttp对象池合理创建和使用xmlhttp对象
- javascript 组成
- EVC下如何直接访问寄存器?
- Kali Linux 2017.3 安装网易云音乐
- js 通过图片URL地址将图片转为可操作的File文件对象
- 风险管理计划包括哪些内容
- 虚拟机win7装oracle,大神教你win7系统安装Oracle VM VirtualBox虚拟机的处理教程
- 标志logo设计/欣赏
- 如何看懂k线图:K线详细分析图解
热门文章
- [Java教程]3.第一个Java程序
- 解决ts运行报错 : 无法加载文件 C:\Users\XXX\AppData\Roaming\npm\webpack.ps1因为在此系统上禁止运行脚本
- 用C语言编写购买地铁车票的规定如下:乘1-4站,3元/位;乘5-9站,4元/位;乘9站以上,5元/位,编写一个程序,利用循环结构、选择结构实现:(1) 输入人数、站数,输出应付款;(2)当
- 名画221 陈继儒《书画合册十二开》
- 第七篇:爬虫实战--- 1、破解滑动验证码
- Delphi 同时支持Windows、Linux、OS X、iOS、Android的新一代跨平台编程语言开发工具
- 2022年游戏蓝牙耳机排行榜:四款口碑最好的游戏蓝牙耳机
- codeforces1549 C. Web of Lies
- 初识javaScript(三)
- 在其他条件不变的前提下,以下哪种做法容易引起机器学习中的过拟合问题()