深入理解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 相关文章推荐
用js重建星际争霸
Dec 22 Javascript
JS 非图片动态loading效果实现代码
Apr 09 Javascript
关于文本框的一些限制控制总结~~
Apr 15 Javascript
ExtJS[Desktop]实现图标换行示例代码
Nov 17 Javascript
从数组中随机取x条不重复数据的JS代码
Dec 24 Javascript
javascript学习笔记之函数定义
Jun 25 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
Oct 23 Javascript
浅析$.getJSON异步请求和同步请求
Jun 06 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
Feb 03 Javascript
关于JavaScript中forEach和each用法浅析
Jul 27 Javascript
深入理解Vue父子组件生命周期执行顺序及钩子函数
Aug 12 Javascript
浅谈react性能优化的方法
Sep 05 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 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
2011/07/17 PHP
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
php制作unicode解码工具(unicode编码转换器)代码分享
2013/12/24 PHP
ThinkPHP调用百度翻译类实现在线翻译
2014/06/26 PHP
thinkphp模板赋值与替换实例简述
2014/11/24 PHP
PHP连接SQLServer2005的方法
2015/01/27 PHP
PHP使用curl模拟post上传及接收文件的方法
2016/03/04 PHP
php头像上传预览实例代码
2017/05/02 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
js获取时间并实现字符串和时间戳之间的转换
2015/01/05 Javascript
详解Vue.use自定义自己的全局组件
2017/06/14 Javascript
详解angular 中的自定义指令之详解API
2017/06/20 Javascript
VsCode新建VueJs项目的详细步骤
2017/09/23 Javascript
解决vue2.0动态绑定图片src属性值初始化时报错的问题
2018/03/14 Javascript
vue cli使用融云实现聊天功能的实例代码
2019/04/19 Javascript
浅谈react-router@4.0 使用方法和源码分析
2019/06/04 Javascript
Vue3.x源码调试的实现方法
2019/10/13 Javascript
如何实现iframe父子传参通信
2020/02/05 Javascript
详解JavaScript 的执行机制
2020/09/18 Javascript
[01:11]回顾历届DOTA2国际邀请赛中国区预选赛
2017/06/26 DOTA
python socket网络编程步骤详解(socket套接字使用)
2013/12/06 Python
Python随机生成均匀分布在单位圆内的点代码示例
2017/11/13 Python
python 字典中取值的两种方法小结
2018/08/02 Python
Python如何调用外部系统命令
2019/08/07 Python
python查看数据类型的方法
2019/10/12 Python
Pytorch之contiguous的用法
2019/12/31 Python
使用tensorflow显示pb模型的所有网络结点方式
2020/01/23 Python
Python装饰器用法与知识点小结
2020/03/09 Python
python3+selenium获取页面加载的所有静态资源文件链接操作
2020/05/04 Python
浅谈CSS3中的变形功能-transform功能
2017/12/27 HTML / CSS
Jacques Lemans德国:奥地利钟表品牌
2019/12/26 全球购物
德国BA保镖药房中文网:Bodyguard Apotheke
2021/03/09 全球购物
JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
2015/10/22 面试题
保密普查工作实施方案
2014/02/25 职场文书
应聘编辑自荐信范文
2014/03/12 职场文书
休学证明范本
2015/06/19 职场文书