加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱制作网_潮州站长网 (http://www.0768zz.com/)- 物联安全、建站、操作系统、云计算、数据迁移!
当前位置: 首页 > 教程 > 正文

JavaScript中的this与函数介绍

发布时间:2021-12-10 12:30:45 所属栏目:教程 来源:互联网
导读:前言 JavaScript中没有块级作用域(es6以前),JavaScript中作用域分为函数作用域和全局作用域。并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码,都存放在Window函数内(这是个假设),也就是说JavaScript中只有函数作用域

前言
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甚至每一门高级语言中都需要的动态绑定的指针。能力一般,水平有限,如有错误,轻喷轻骂。

(编辑:我爱制作网_潮州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读