深入理解js函数的作用域与this指向


Posted in Javascript onMay 28, 2016

函数的作用域与this指向是js中很重要的一部分,理清这点东西需要个逻辑,看看我的逻辑怎么样...

下面是个提纲,可以直接挑你感兴趣的条目阅读。

• 函数的定义方式:直接定义(window下,内部定义),对象的方法,对象原型的方法;

• 函数的调用方式:直接调用,call/apply,with

• 对于直接定义的函数和对象的方法,作用域默认状态下是它的定义处的作用域链。

• 对于直接定义的函数,this指向window。

• 对于对象的方法,this指向实例化对象(对应于实例化对象默认返回this的情况)。

• 用call/apply改变方法的this指向

• 在函数或方法的定义时可以通过with改变其作用域链。

下面分开来具体说说:

函数的定义,如提纲中提到的可以分为两种:直接定义(window下,内部定义),对象的方法(或对象原型的方法)。从下面的示例代码中可以看到函数fn1与fn2以及对象的方法doFunction在函数使用name时name的值来自相应的域。

 

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += name;

在使用name的值时将“name”用“this.name”来代替会出现什么情况呢,看下例:

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += this.name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += this.name;

从结果来看可以验证提纲中的第4和5条,也可以看到this和作用域是两套分离的链,遵循个自的变量查询逻辑,具体的查询逻辑在下面的性能分析中会提到,如果是新手建议先看一下“js的作用域链”方面的基础知识。

 关于函数的调用方法,我用下面的方示例说明提纲中的第2、6条:

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += this.name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += this.name;

调用时call和apply的使用是为了改变被调用函数的this指向。with的使用是为了改变被调用函数中变量的查询域。我们把上例中的call和name前的this去掉再加上with来演示with的作用。

var name = 'window下的name<br/>';
var resultCon;
function fn1(myScope) {
  with (myScope) {
    resultCon.innerHTML += name;
  }
}

function MyObj(myScope) {
  var name = 'MyObj下的name<br/>';

看到with的使用并不方便,需要在被调用函数中添加with,有人可能想能不能向下面那样调用来整体改变变量作用域而不去改变被调用函数呢?

with (myScope) {
  fn1();
  fn2();
  var obj = new MyObj();
  obj.doFunction();
}

很遗憾,不可以!所以在一些成熟的框架中随处可见call和apply的使用,却很少用到with,在用JSHint检测js语法的时候with处都标了小红点,在一些js编码指导中也建议尽量少用with,因为with改变了变量的默认查询链,所以会给后期的维护人员一些困惑,还有性能方面的一些考虑,请慎用with。

以上这篇深入理解js函数的作用域与this指向就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
filters.revealTrans.Transition使用方法小结
Aug 19 Javascript
jquery插件 autoComboBox 下拉框
Dec 22 Javascript
Android中资源文件(非代码部分)的使用概览
Dec 18 Javascript
js获取url参数代码实例分享(JS操作URL)
Dec 13 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
Mar 22 Javascript
JavaScript 网页中实现一个计算当年还剩多少时间的倒数计时程序
Jan 25 Javascript
折叠菜单及选择器的运用
Feb 03 Javascript
JS对象是否拥有某属性如何判断
Feb 03 Javascript
angular 用拦截器统一处理http请求和响应的方法
Jun 08 Javascript
jQuery EasyUI结合zTree树形结构制作web页面
Sep 01 jQuery
Vue-cli3项目配置Vue.config.js实战记录
Jul 29 Javascript
Vue双向绑定实现原理与方法详解
May 07 Javascript
js和C# 时间日期格式转换的简单实例
May 28 #Javascript
JS函数arguments数组获得实际传参数个数的实现方法
May 28 #Javascript
深入理解JS函数的参数(arguments)的使用
May 28 #Javascript
深入理解js中this的用法
May 28 #Javascript
关于function类中定义变量this的简单说明
May 28 #Javascript
Highcharts 多个Y轴动态刷新数据的实现代码
May 28 #Javascript
动态更新highcharts数据的实现方法
May 28 #Javascript
You might like
基于php设计模式中工厂模式详细介绍
2013/05/15 PHP
phpexcel导入excel数据使用方法实例
2013/12/24 PHP
Php中使用Select 查询语句的实例
2014/02/19 PHP
ASP和PHP实现生成网站快捷方式并下载到桌面的方法
2014/05/08 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
thinkphp5修改view到根目录实例方法
2019/07/02 PHP
详解强大的jQuery选择器之基本选择器、层次选择器
2012/02/07 Javascript
解析Javascript中中括号“[]”的多义性
2013/12/03 Javascript
JS数组排序方法实例分析
2016/12/16 Javascript
js 颜色选择插件
2017/01/23 Javascript
详解node+express+ejs+bootstrap构建项目
2017/09/27 Javascript
Easy UI动态树点击文字实现展开关闭功能
2017/09/30 Javascript
vue-cli 引入、配置axios的方法
2018/05/08 Javascript
vue-cli 打包使用history模式的后端配置实例
2018/09/20 Javascript
js尾调用优化的实现
2019/05/23 Javascript
vue实现点击出现操作弹出框的示例
2020/11/05 Javascript
[01:38]完美世界DOTA2联赛PWL S3 集锦第四期
2020/12/21 DOTA
python中__call__方法示例分析
2014/10/11 Python
Python多线程编程(五):死锁的形成
2015/04/05 Python
Python装饰器使用实例:验证参数合法性
2015/06/24 Python
Python3 模块、包调用&amp;路径详解
2017/10/25 Python
Python利用正则表达式实现计算器算法思路解析
2018/04/25 Python
Django框架模板用法入门教程
2019/11/04 Python
wxPython实现分隔窗口
2019/11/19 Python
selenium中get_cookies()和add_cookie()的用法详解
2020/01/06 Python
在python中logger setlevel没有生效的解决
2020/02/21 Python
幼儿园义卖活动方案
2014/01/17 职场文书
会计学生自我鉴定
2014/02/06 职场文书
初中家长寄语
2014/04/02 职场文书
项目投资合作意向书
2014/07/29 职场文书
见义勇为事迹材料
2014/12/24 职场文书
大学生年度个人总结
2015/02/15 职场文书
2019 入党申请书范文
2019/07/10 职场文书
教你使用TensorFlow2识别验证码
2021/06/11 Python
详解overflow:hidden的作用(溢出隐藏、清除浮动、解决外边距塌陷)
2021/07/01 HTML / CSS