深入理解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 相关文章推荐
向大师们学习Javascript(视频与PPT)
Dec 27 Javascript
JavaScript避免代码的重复执行经验技巧分享
Apr 17 Javascript
JavaScript-RegExp对象只能使用一次问题解决方法
Jun 23 Javascript
深入分析jquery解析json数据
Dec 09 Javascript
javascript正则表达式使用replace()替换手机号的方法
Jan 19 Javascript
javascript执行环境及作用域详解
May 05 Javascript
JS构造函数与原型prototype的区别介绍
Jul 04 Javascript
Base64(二进制)图片编码解析及在各种浏览器的兼容性处理
Feb 09 Javascript
详解微信小程序 template添加绑定事件
Jun 23 Javascript
Angular4编程之表单响应功能示例
Dec 13 Javascript
Angularjs之ngModel中的值验证绑定方法
Sep 13 Javascript
解决vue axios的封装 请求状态的错误提示问题
Sep 25 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/06/09 PHP
PHP下获取上个月、下个月、本月的日期(strtotime,date)
2014/02/02 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
JQuery 选择和过滤方法代码总结
2010/11/19 Javascript
初学js插入节点appendChild insertBefore使用方法
2011/07/04 Javascript
JS获取月份最后天数、最大天数与某日周数的方法
2015/12/08 Javascript
基于jQuery实现Tabs选项卡自定义插件
2016/11/21 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
深入理解Nodejs Global 模块
2017/06/03 NodeJs
Angular2里获取(input file)上传文件的内容的方法
2017/09/05 Javascript
JavaScript实现图片伪异步上传过程解析
2020/04/10 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
Vue多选列表组件深入详解
2021/03/02 Vue.js
python中的reduce内建函数使用方法指南
2014/08/31 Python
python对html代码进行escape编码的方法
2015/05/04 Python
python实现一个简单的并查集的示例代码
2018/03/19 Python
Python自定义线程类简单示例
2018/03/23 Python
python多线程调用exit无法退出的解决方法
2019/02/18 Python
python模拟菜刀反弹shell绕过限制【推荐】
2019/06/25 Python
python实现实时视频流播放代码实例
2020/01/11 Python
TensorFlow获取加载模型中的全部张量名称代码
2020/02/11 Python
Python 捕获代码中所有异常的方法
2020/08/03 Python
Css3+Js制作漂亮时钟(附源码)
2013/04/24 HTML / CSS
html5 Canvas绘制线条 closePath()实例代码
2012/05/10 HTML / CSS
HTML5拖拽功能实现的拼图游戏
2018/07/31 HTML / CSS
Farnell德国:电子元器件供应商
2018/07/10 全球购物
Antonioli美国在线商店:时尚前卫奢华
2019/07/29 全球购物
意大利文具和办公产品在线商店:Y-Office
2020/02/27 全球购物
如果让你测试一台高速激光打印机,你都会进行哪些测试
2012/12/04 面试题
求职信范文英文版
2014/01/05 职场文书
甜点店创业计划书
2014/01/27 职场文书
《一个中国孩子的呼声》教学反思
2014/02/12 职场文书
鲁迅故里导游词
2015/02/05 职场文书
单位更名证明
2015/06/18 职场文书
关于PHP数组迭代器的使用方法实例
2021/11/17 PHP
Java工作中实用的代码优化技巧分享
2022/04/21 Java/Android