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相关推荐

  1. 学JS的心路历程-函式(五)箭头函式

    箭头函式arrow function 为了能够以更简短的方式建立函式,ES6变推出了箭头函式. 用说明的可能会不太懂,我们先拿之前的数组排序例子来看: var arr = [2,1,6,12,3,77 ...

  2. 学习JS的心路历程-函式(一)

    前几天有间单提到该如何声明函式及在Hositing中会发生什么事,但是函式的奥妙不仅于此. 身为一个使用JS的工程师,我们一定要熟悉函式到比恋人还熟! 这几天将会把函式逐一扒开跟各位一起探讨其中的奥妙 ...

  3. 学JS的心路历程 -物件与原型(二)

    昨天有提到说Object.setPrototypeOf可以指定一个物件为另一个物件的原型,但有想过到底这个原型,也就是[[Prototype]]最终会到何处吗? 答案是Object.prototype ...

  4. 学JS的心路历程 -非同步执行

    JS是单线程的语言,也就是说同一时间只会执行一行程序,所以如果一段程序执行过久就会造成阻塞(blocking)的现象,必须等到它结束后才能执行下一段程序. 举个例子来说,如果我们今天要买便当,但是老板 ...

  5. 学JS的心路历程 -数组常见处理方法

    昨天我们有提到说for-of和forEach可以用来处理数组,但其实还有很多方法可以更快速及精简代码的达到你要的效果. 话不多说,我们赶紧来看吧! Array.prototype.map() 会回传一 ...

  6. 学JS的心路历程-Promise(一)

    今天在进入Promise代码之前,我们先来用个例子来解释Promise是什么. 未来值 假设我们今天来到快餐店,点了一个汉堡,付钱给店员. 点了餐点并付费,可以理解为我们发送了一个请求,希望得到一个回 ...

  7. 学JS的心路历程Day28 - PixiJS -基础(二)

    材质暂存(texture cache) 昨天有说到,图片要放入stage前,需要先把图片转成Sprite的特殊图片物件. 但是我们也可以先将图片放进材质暂存(texture cache). 什么是「材 ...

  8. 学习JS的心路历程-参数传递方式(上)

    很多人认为JS的传递方式是值是Call by value, 物件及数组是Call by Reference.甚至还有人宣称其实JS是Call by sharing,那到底是哪一个呢? 这两天我们一一来 ...

  9. 尤雨溪创立 Vue.js 的心路历程纪录片

    Show More 本文分享自微信公众号 - 生信科技爱好者(bioitee). 如有侵权,请联系 support@oschina.cn 删除. 本文参与"OSC源创计划",欢迎正 ...

最新文章

  1. ffmpeg-win32-v3.2.4 下载_iTools下载|iTools 4.4.3.4 官方中文版
  2. DirectionalLayout线性布局
  3. boost::mp11::mp_pairwise_fold相关用法的测试程序
  4. [BZOJ3566][SHOI2014]概率充电器
  5. pythontcp服务器如何关闭阻塞_python 网络编程(socketserver,阻塞,其他方法)
  6. android转usb工具,绿联Type-C转Micro usb数据线,Type-C转安卓接口转换线
  7. 【渝粤教育】电大中专消费者行为学 (2)作业 题库
  8. 使用Secure Boot后,导致VMware无法启动虚拟机
  9. 2019年四月计算机语言排名,2019编程排行榜_编程语言排行榜2019年4月 TIOBE编程语言排行榜2019年最新版...
  10. 【java】Spring开发中不能使用IOC的情况
  11. 03惯性导航系统误差分析
  12. Android App脱壳
  13. 一无所知学编程:Jargon File(1)
  14. python怎么取共轭_python print出共轭复数的方法详解
  15. springboot启动原理及其流程
  16. 【Golang开发面经】深信服(两轮技术面)
  17. 使用Dockerfile创建包含nginx-fair和nginx-check模块的nginx镜像
  18. 什么?一个核同时执行两个线程?
  19. Java:do、dto、bo、ao、vo、pojo
  20. 从马文到AlphaGo AI走过了怎样的70年?

热门文章

  1. HDU-3280 Equal Sum Partitions
  2. obj.toSource()
  3. MySQL(一)——安装、创建数据库表、DML语言
  4. Mysql商品和图片表_【mysql】数据库设计模式:多个图片怎么和商品关联
  5. 使用Anaconda完全替代官方Python
  6. 北斗导航 | 基于RTK的GNSS与多源融合定位技术发展与挑战
  7. CEdit里''\r\n才是换行
  8. linux lynx 源码,Lynx字符浏览器移植
  9. mysql insert慢_MySQL insert语句慢查询的优化
  10. 电工结业试卷_电工电子考试试(含答案).doc