前言

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执行,会首先产生一个函数活动对象,这个活动对象对外是不可见的,该示例中,call方法先绑定了此次调用的this指向o,fn函数活动对象通过参数之间的赋值形成arguments对象,然后进行了函数内部的初始化变量,最后执行函数内部的赋值过程。过程如下:

function fn (a = 1, b = 'ok') {
var c
var f
//活动对象初始化完毕,进行函数体内的其他操作,这根变量提升和函数声明提升有关
c = 2
f = function () {...}
}

总结

总而言之,函数是javascript中最主要的结构,this是javascript甚至每一门高级语言中都需要的动态绑定的指针。能力一般,水平有限,如有错误,轻喷轻骂。

javascript中的this与函数讲解的更多相关文章

  1. avascript中的this与函数讲解

    徐某某 一个半路出家的野生程序员 javascript中的this与函数讲解 前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大 ...

  2. [转]Javascript中的自执行函数表达式

    [转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...

  3. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  4. 使用Ajax在javascript中调用后台C#函数

    使用Ajax在javascript中调用后台C#函数 最近一段时间在紧跟一个网站的项目,数据库中用户表的UserName要求是唯一的,所以当用户选定一个用户名进行注册时要首先检查该用户名是否已被占用, ...

  5. 在javascript中关于变量与函数的提升

    在javascript中关于变量与函数的提升 一.简介 在javascript中声明变量与函数的执行步骤: 1.先预解析变量或函数声明代码,会把用var声明的变量或者函数声明的代码块进行提升操作 2. ...

  6. javascript中的立即执行函数(function(){…})()

    javascript中的立即执行函数(function(){…})() 深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包 ...

  7. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

  8. JavaScript中的内置函数

    JavaScript中的内置函数 制作人:全心全意 在使用JavaScript语言时,除了可以自定义函数之外,还可以使用JavaScript的内置函数,这些内置函数是由JavaScript语言自身提供 ...

  9. JavaScript 中对变量和函数声明提前的演示样例

    如题所看到的,看以下的演示样例(能够使用Chrome浏览器,然后F12/或者右键,审查元素.调出开发人员工具,进入控制台console输入)(使用技巧: 控制台输入时Shift+Enter能够中途代码 ...

随机推荐

  1. java Web项目创建之一(普通java web项目的创建与发布)

    1.创建新的web项目 file->new_>Dynamic Web Project(如图) 或file->new->Project->Web->Dynamic W ...

  2. Oracle手边常用70则脚本知识汇总

    Oracle手边常用70则脚本知识汇总 作者:白宁超 时间:2016年3月4日13:58:36 摘要: 日常使用oracle数据库过程中,常用脚本命令莫不是用户和密码.表空间.多表联合.执行语句等常规 ...

  3. duang~免费的学习视频来啦:学霸君之全栈测试

    学霸君向童鞋们推荐一款 同名学霸学习 视频教程 重点是完全免费收看学习噢!!! 今天 学霸君推荐腾讯课堂的学霸君之全栈测试 复制下方链接至腾讯课堂中报名学习 https://ke.qq.com/cou ...

  4. UVa 122 Trees on the level

    题目的意思: 输入很多个节点,包括路径和数值,但是不一定这些全部可以构成一棵树,问题就是判断所给的能否构成一棵树,且没有多余. 网上其他大神已经给出了题目意思:比如我一直很喜欢的小白菜又菜的博客 说一 ...

  5. Java中,异常的处理及抛出

    首先我们需要知道什么是异常? 常通常指,你的代码可能在编译时没有错误,可是运行时会出现异常.比如常见的空指针异常.也可能是程序可能出现无法预料的异常,比如你要从一个文件读信息,可这个文件不存在,程序无 ...

  6. 设计模式C#合集--抽象工厂模式

    抽象工厂,名字就告诉你是抽象的了.上代码. public interface BMW { public void Drive(); } public class BMW730 : BMW { publ ...

  7. autocomplete的使用

    autocomplete使用分为本地调用方法和读取远程读取数据源的方法 (1)本地调用方法 <script src="Scripts/jquery-1.4.1.min.js" ...

  8. SOLID 设计原则

    SOLID 原则基本概念: 程序设计领域, SOLID (单一功能.开闭原则.里氏替换.接口隔离以及依赖反转)是由罗伯特·C·马丁在21世纪早期 引入的记忆术首字母缩略字,指代了面向对象编程和面向对象 ...

  9. prometheus监控系统

    关于Prometheus Prometheus是一套开源的监控系统,它将所有信息都存储为时间序列数据:因此实现一种Profiling监控方式,实时分析系统运行的状态.执行时间.调用次数等,以找到系统的 ...

  10. 微信小程序开发日记——高仿知乎日报(中)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教 ...