学JS的心路历程 -函式(三)this
this是什么,取决于被呼叫的呼叫地点。
昨天有提到说,呼叫函式时候会传递隐含参数:arguments和this并讲解了arguments,今天我们就来探讨this吧!
什么是this
我们都会呼叫函式来使用,但有想过到底是从哪里呼叫到这个函式吗?
this通常被称作函式背景空间(function context),也就是说透过this我们可以知道到底是由谁呼叫这支函式(yjssqsdg)。我们无法在一开始定义它,只有函式呼叫时候才能确定。
函式的呼叫有四种方式:
作为函式呼叫
作为一个(物件)的方法呼叫
作为一个建构式函式呼叫
透过apply、call呼叫
apply、call我们会在下一篇中介绍,我们今天主要介绍上述三种呼叫方式。
作为函式呼叫
function funA(){
console.log(this);
}
funA();//Window
由于是在全局环境呼叫funA,所以这时候的this就会是window。
所以很多刚学习的人都会遇到这个问题:
function funA(){
this.count ++;
}
funA.count = 0;
funA();
console.log(funA.count);//0
明明已经声明funA.count = 0怎么会没有加到呢?这就是因为funA是被全局环境也就是window呼叫,所以this并不是你预期的funA。
那到底加了谁的count呢?你可以尝试印出window.count会发现是NaN,是因为你赋予window一个count属性且一开始没有给定初始值,
所以会变成undefined+ 1 = NaN。
或许你认为这样就可以解决问题:
function funA(val){
val.count ++;
}
var dart = {
count:0
};
funA(dart);
console.log(dart.count);//1
但这样你只是在逃避this这个问题而已!!
要透过this解决方案有两种,一个是等下提到的作为物件的方法;一个是明天会说的call及apply。
作为方法呼叫
函式可以透过写在物件里面去呼叫,这个呼叫方式称作作为方法(method),相信大家都知道,但你知道在这时候的this是什么吗?
var obj = {
funA:function(){
console.log(this);
console.log(this===obj);
}
}
obj.funA();
//{funA:ƒ}
//true
可以看到这时候的this是obj物件,也是是说我们是透过obj去呼叫的。
但是要注意一个小地方:
function funA(){
console.log(this);
console.log(this===obj);
}
var obj = {
a:funA
}
funA();
//Window
//false
虽然你认为我已经让obj参照funA了,但是当你直接执行funA时,还是由全局环境去呼叫,这也呼应了我们开头所说的「我们无法在一开始定义它,只有函式呼叫时候才能确定」。
我们可以利用作为方法呼叫来解决作为函式呼叫的问题:
function funA(){
this.count ++;
}
var obj = {
count:0,
sum:funA
};
obj.sum();
console.log(obj.count);//1
作为建构式呼叫
建构式的函式声明就跟任何函式一样,也可以用声明和表达来建立新物件。
要作为建构式函式来呼叫函式,必须要在函式呼叫前加上new:
function myConstructor(){
this.count = 0;
this.sum = function(){
return this.count ++
}
}
var a = new myConstructor();
a.sum();
console.log(a.count);
也许有人会觉得,这跟作为方法呼叫很像,那用物件去写就好何必这么麻烦还要学建构式,用奇怪的new去呼叫函式。
这边就来说明一下,使用new呼叫函式时,会发生什么事:
建立一个新物件。
此物件被当成this参数传递给建构式,因此成为建构式的函式背景空间(swrebar)。
回传新建立的物件。
如果我们今天需要两个相同的物件,如果用作为物件方法呼叫的话就必须建立两个不同的物件,否则会参照到同样的物件并修改。
但是建构式就不需要,因为每一个都是一个新的物件:
function myConstructor(){
this.count = 0;
this.sum = function(){
return this.count ++
}
}
var a = new myConstructor();
var b = new myConstructor();
a.sum();
console.log(b.count);//0
以上就是this的基本三种呼叫方式,若有错误及参考资料未附上劳请留言。
明天我们会介绍this的稍微进阶应用call及apply。
参考资料:
忍者JavaScript开发技巧探秘
你所不知道的JS - this
彻底理解js中this的指向,不必硬背。
转载于:https://www.cnblogs.com/lannyQ-Q/p/9935901.html
学JS的心路历程 -函式(三)this相关推荐
- 学JS的心路历程-函式(五)箭头函式
箭头函式arrow function 为了能够以更简短的方式建立函式,ES6变推出了箭头函式. 用说明的可能会不太懂,我们先拿之前的数组排序例子来看: var arr = [2,1,6,12,3,77 ...
- 学习JS的心路历程-函式(一)
前几天有间单提到该如何声明函式及在Hositing中会发生什么事,但是函式的奥妙不仅于此. 身为一个使用JS的工程师,我们一定要熟悉函式到比恋人还熟! 这几天将会把函式逐一扒开跟各位一起探讨其中的奥妙 ...
- 学JS的心路历程 -物件与原型(二)
昨天有提到说Object.setPrototypeOf可以指定一个物件为另一个物件的原型,但有想过到底这个原型,也就是[[Prototype]]最终会到何处吗? 答案是Object.prototype ...
- 学JS的心路历程 -非同步执行
JS是单线程的语言,也就是说同一时间只会执行一行程序,所以如果一段程序执行过久就会造成阻塞(blocking)的现象,必须等到它结束后才能执行下一段程序. 举个例子来说,如果我们今天要买便当,但是老板 ...
- 学JS的心路历程 -数组常见处理方法
昨天我们有提到说for-of和forEach可以用来处理数组,但其实还有很多方法可以更快速及精简代码的达到你要的效果. 话不多说,我们赶紧来看吧! Array.prototype.map() 会回传一 ...
- 学JS的心路历程-Promise(一)
今天在进入Promise代码之前,我们先来用个例子来解释Promise是什么. 未来值 假设我们今天来到快餐店,点了一个汉堡,付钱给店员. 点了餐点并付费,可以理解为我们发送了一个请求,希望得到一个回 ...
- 学JS的心路历程Day28 - PixiJS -基础(二)
材质暂存(texture cache) 昨天有说到,图片要放入stage前,需要先把图片转成Sprite的特殊图片物件. 但是我们也可以先将图片放进材质暂存(texture cache). 什么是「材 ...
- 学习JS的心路历程-参数传递方式(上)
很多人认为JS的传递方式是值是Call by value, 物件及数组是Call by Reference.甚至还有人宣称其实JS是Call by sharing,那到底是哪一个呢? 这两天我们一一来 ...
- 尤雨溪创立 Vue.js 的心路历程纪录片
Show More 本文分享自微信公众号 - 生信科技爱好者(bioitee). 如有侵权,请联系 support@oschina.cn 删除. 本文参与"OSC源创计划",欢迎正 ...
最新文章
- ffmpeg-win32-v3.2.4 下载_iTools下载|iTools 4.4.3.4 官方中文版
- DirectionalLayout线性布局
- boost::mp11::mp_pairwise_fold相关用法的测试程序
- [BZOJ3566][SHOI2014]概率充电器
- pythontcp服务器如何关闭阻塞_python 网络编程(socketserver,阻塞,其他方法)
- android转usb工具,绿联Type-C转Micro usb数据线,Type-C转安卓接口转换线
- 【渝粤教育】电大中专消费者行为学 (2)作业 题库
- 使用Secure Boot后,导致VMware无法启动虚拟机
- 2019年四月计算机语言排名,2019编程排行榜_编程语言排行榜2019年4月 TIOBE编程语言排行榜2019年最新版...
- 【java】Spring开发中不能使用IOC的情况
- 03惯性导航系统误差分析
- Android App脱壳
- 一无所知学编程:Jargon File(1)
- python怎么取共轭_python print出共轭复数的方法详解
- springboot启动原理及其流程
- 【Golang开发面经】深信服(两轮技术面)
- 使用Dockerfile创建包含nginx-fair和nginx-check模块的nginx镜像
- 什么?一个核同时执行两个线程?
- Java:do、dto、bo、ao、vo、pojo
- 从马文到AlphaGo AI走过了怎样的70年?
热门文章
- HDU-3280 Equal Sum Partitions
- obj.toSource()
- MySQL(一)——安装、创建数据库表、DML语言
- Mysql商品和图片表_【mysql】数据库设计模式:多个图片怎么和商品关联
- 使用Anaconda完全替代官方Python
- 北斗导航 | 基于RTK的GNSS与多源融合定位技术发展与挑战
- CEdit里''\r\n才是换行
- linux lynx 源码,Lynx字符浏览器移植
- mysql insert慢_MySQL insert语句慢查询的优化
- 电工结业试卷_电工电子考试试(含答案).doc