avascript中的this与函数讲解
javascript中的this与函数讲解
前言
javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域。并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码,都存放在Window函数内(这是个假设),也就是说javascript中只有函数作用域(前面假设做前提下)。
作用域是什么
作用域是一个盒子,盒子内部的变量只能在当前盒子中使用,作用域盒子是可以嵌套的,内部盒子的变量对父级盒子是不可见的,因为盒子封闭了他们并且盒子不透明,但是盒子可以看到父级盒子内部定义的变量,因为内部这个盒子与父级的变量同处一个空间,他们是互相看得到的。就像css中的盒模型一样。
以上这个图分为3层作用域,全局作用域、foo函数作用域、bar函数作用域,我们可以清晰的看到三层作用域各自的范围。
this是什么
我们经常用到this,this是代表着什么?this是代表着当前方法执行的环境上下文,那么何为环境上下文,通俗的说,谁调用了函数,谁就是这个函数的环境上下文。例如:
function run () {
console.log(this)
} var o = {
run: run
} run() // window对象
o.run // o对象
在上述代码中,run是一个函数,首先执行run()返回了window对象,为什么呢?我们已经讲过,var定义的变量会默认挂在到window对象中去,那么function定义的函数呢,也会默认挂在到window对象中去,其实我们在执行一个函数如:run() 跟window.run()是一样的,所以,window调用了run,因此函数的this是window。
注意:this的绑定是产生在函数调用时,并非在函数定义时
var o = {
color: 'red',
getColor: function () {
console.log(this.color)
}
} var color = 'blue' var getColor = o.getColor o.getColor // red
getColor // blue
上述代码,我们将o.getColor方法赋值给了一个变量getColor,然后我们分别执行了两个方法,缺得到了不同的结果,对于o.getColor并没有什么疑问,但是初学者可能认为getColor返回的也应该是red,但事实是blue,这就说明了,this是产生在函数调用时,因为在o.getColor赋值语句,就相当于一下语句
var getColor = function () {
console.log(this.color)
}
o.getColor返回的是这个函数,并没有绑定this,也就是说getColor其实是被赋值了一个函数,仅此而已,this是在调用时绑定的,所以得到了那样的结果。
不要被模样给蒙蔽
看下面代码:
var o = {
run : function () {
setTimeout(function () {
console.log(this)
}, 1000)
}
}
o.run() // window对象
以上运行了o.run方法,隔一秒输出this,输出了window对象,初学者可能会疑问,o.run调用时明明是在o对象下啊,this应该是o对象啊!不错,有这个疑问说明对this有一定了解了,但是上面案例是在setTimeout方法中的回调函数中输出的this,此回调函数执行时,是以fn()方式执行的(涉及到异步回调),前面说过直接执行函数相当于window.fn,因此输出了window对象。
拓展回调:
回调是进行异步操作常用的功能,上面示例中,我们可以假设为setTimeout是这样定义的
function setTimeout (fun) {
fun()
} setTimeout (function () {
console.log(this)
})
可以看出,fun是直接调用的,输出的this必定是window对象。
暴力绑定this
有时候,我们需要强制某个函数中的this为某一对象,我们这时候需要暴力的绑定this,这里,暴力的方法有3个: call、apply、bind。下面通过一个简单的demo来看一下他们的用法。
var color = 'blue' var o = {
color: 'red',
say: function (animal, beautiful) {
console.log(this.color + '颜色的' + animal + (beautiful ? '好看': '不好看'))
}
} var say= o.say say('猫', false) // blue颜色的猫不好看
say.call(o, '猫', true) // red颜色的猫好看
say.apply(o, ['猫', true]) // red颜色的猫好看
say.bind(o)('猫', true) // red颜色的猫好看
o.say.call(null, '猫', false) // blue颜色的猫不好看
我们这次将o函数加一个say方法,say方法接收两个参数,第一个数动物,第二个是布尔值代表好不好看,我们还是将o.say赋值给变量say。
say('猫', false) 如期返回了blue颜色
say.call(o, '猫', true),say.apply(o, ['猫', true]),say.bind(o)('猫', true) 这三个都返回了red,可见我们都暴力的绑定了this为o对象。
call和apply的第一个参数都是接收要绑定的对象,也就是告诉引擎:'我要让say方法在o对象的环境下运行,你给我帮顶一下',引擎回答:‘包在我身上’,然后我们就绑定成功了,接下来我们需要传递参数到方法中去,call方法是在第二个参数之后,按顺序的传递参数 到方法中去,apply方法不同,apply方法是在第二个参数以数组的方式将参数传递到方法中去。而bind方法是es5中的方法,用途就在于绑定this指向然后返回已绑定好了的函数,因此,以上三个都输出了red
同样o.say绑定到null或者undefined,引擎会自动绑定到全局对象window下面。
进阶:函数的执行过程
本着菜鸟的思路,努力讲述一下简单的函数执行背后的历程,有错误请指正。
function fn (a, b) {
var c = 2;
function f () {...}
} var o = {} fn.call(o,1,'ok')
函数fn执行,会首先产生一个函数活动对象,这个活动对象对外是不可见的,该示例中,fn函数活动对象先绑定了此次调用的this指向o,参数之间的赋值形成arguments对象,然后进行了函数内部的初始化变量,最后执行函数内部的赋值过程。过程如下:
function fn (a = 1, b = 'ok') {
var c
var f
//活动对象初始化完毕,进行函数体内的其他操作,这根变量提升和函数声明提升有关
c = 2
f = function () {...}
}
总结
总而言之,函数是javascript中最主要的结构,this是javascript甚至每一门高级语言中都需要的动态绑定的指针。能力一般,水平有限,如有错误,轻喷轻骂。
avascript中的this与函数讲解的更多相关文章
- javascript中的this与函数讲解
前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...
- numpy中transpose和swapaxes函数讲解
1 transpose() 这个函数如果括号内不带参数,就相当于转置,和.T效果一样,而今天主要来讲解其带参数. 我们看如下一个numpy的数组: arr=np.arange(16).reshape( ...
- Spark Streaming中的操作函数讲解
Spark Streaming中的操作函数讲解 根据根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transform ...
- SQL中的存储过程和函数
存储过程和函数 简单的说,存储过程就是一条或者多条SQL语句的集合.可以视为批文件,但是其作用不仅仅局限于批处理.本文主要介绍如 ...
- 【PHP】最详细PHP从入门到精通(三)——PHP中的数组常用函数汇总
PHP从入门到精通 之PHP中的数组常用函数详解 数组作为PHP中最常用的结构之一,PHP强大的数组函数功能,给数组的相关操作带来了极大的便利.今天给大家介绍的PHP中数组函数,是PHP数组中重要的 ...
- Shell脚本中使用function(函数)示例
这篇文章主要介绍了Shell脚本中使用function(函数)示例,本文着重讲解的是如何在shell脚本中使用自定义函数,并给出了两个例子,需要的朋友可以参考下 函数可以在shell script ...
- Python中高阶函数讲解
高阶函数讲解 1. 常规高阶函数 递归函数 格式:def func_name(variable): '''__doc__'''#函数的说明文档 if 条件表达式:#限制递归退出值 pass retur ...
- php中常用的正则表达式函数
php中常用的正则表达式函数 * preg_match() * preg_match_all() * preg_replace() * preg_filter() * preg_grep() * pr ...
- MySql UNIX_TIMESTAMP和FROM_UNIXTIME函数讲解
MySql UNIX_TIMESTAMP和FROM_UNIXTIME函数讲解 by:授客 QQ:1033553122 1. unix_timestamp(date)将时间转换为时间戳,如果参数为空,则 ...
随机推荐
- ssh 使用
svn 删除所有的 .svn文件 find . -name .svn -type d -exec rm -fr {} \; linux之cp/scp命令+scp命令详解 注意:本篇以后设涉及到的@后面 ...
- IO(1)
java的IO主要在java.io包下,包括字节流和字符流. 1 File File类可以对文件和目录进行操作,就是不能访问文件本身,其常用方法包括: 1)String getName(),返回fil ...
- Linux学习笔记(11)-kill函数
明天开始学习kill函数的用法. ---------------------------------------------- kill函数可以用来向指定的进程发送一个指定的信号,在我的理解的来看,就 ...
- Daily Scrum Meeting ——FifthDay(Beta)12.13
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1.制作注册分流的头像 发布者头像 参与者头像 2.完成参与者上传头像的功能:通过本 ...
- 安卓智能POS终端手持机PDA应用仓库出入库,移库,盘点,销售开单系统
随着移动互联网的兴起,目前仓储管理所面临的的问题可以迎刃而解,WMS仓库系统解决方案通过智能终端扫描条码技术应用解决了工作量大导致工作效率不高,以及数据实时传输等问题,该方案主要提供仓库出入库,移库, ...
- Vue - 在v-repeat中使用计算属性
1.从后端获取JSON数据集合后,对单条数据应用计算属性,在Vue.js 0.12版本之前可以在v-repeat所在元素上使用v-component指令 在Vue.js 0.12版本之后使用自定义元素 ...
- SPOJ DQUERY D-query(主席树)
题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...
- 【转】SHELL中的IFS详解
转自:http://smilejay.com/2011/12/bash_ifs/ 在bash中IFS是内部的域分隔符,manual中对其的叙述如下: IFS The Internal Field Se ...
- jquery 获取奇数索引的元素
$(".btn-xs:odd").click(function(){ var $buy_num=$(this).prev("#buy_num").val(); ...
- es6转es5
一.在没有IDE情况下的转换 在"我的电脑->D盘”新建个文件夹es6,文件夹里新建一个文件es6.js. 打开命令行窗口 1.先全局安装babel-cli,输入命令 npm inst ...