JavaScript this在函数中的指向及实例详解


Posted in Javascript onOctober 14, 2019

一、this,其实可以类比成人

说到this的话,我们在js中主要研究的都是函数中的this,在javascript中,this代表当前行为的执行主体,而context代表的是当前行为执行的的环境(区域)。

例如男神在北理珠吃饭,这句话分别代表的含义如下

男神 -->> 主体(this)

吃饭 -->> 函数(function)

北理珠 -->> 环境(context)

-->>说明:吃饭是函数,男神是函数的主体,北理珠就是当前行为的执行环境(context),主体跟上下文没有必然的联系,主体只与函数有关系;就好像男神吃饭,其实哪里都可以吃饭,吃饭这个动作的主体永远都是男神,环境是可以变化的。

-->>结论:上面,其实也可以说明,this指的是谁,和函数在哪里定义和执行是没有任何关系的。

二、在函数中,如何区分this

1、函数执行,首先看函数名前面是否有“.” ,有的话, “.”前面是谁,this就是谁;没有的话this就是window

//例子一
console.log(this);
function eat() {
  console.log(this); //this->window
}
~function() {
  eat(); //this->window
}();
 
//例子二
function fn() {
  console.log(this); 
}
var obj = {fn: fn};
fn(); //this->window
obj.fn() //this->obj
 
//例子三
function sum() {
  fn(); 
}
sum(); //this->window
 
//例子四
var oo = {
  sum: function() {
    console.log(this);
    fn();
  }
}
oo.sum(); //首先sum函数里面,第一个输出this为oo;之后执行fn(),this为window

2、立即执行函数中的this永远都是window

(function() {
  console.log(this); // this->window
})()

3、给元素的某一事件绑定方法,当事件触发的时候,执行对应的方法,方法中的this是当前元素

function fn() {
  console.log(this);
}
//例子一
document.getElementById("div1").onclick = fn; //this -> dom元素
//例子二
document.getElementById("div1").onclick = function() {
  console.log(this); // this->#div
  fn(); // this->window
}

结论: 找到函数在哪里执行的,有点,this就是点前面东西;没点,this就是window

三、使用this分析一道面试题

var num = 20;
var obj = {
  num: 30,
  fn: (function(num) {
    this.num *= 3;
    num += 15;
    var num = 45;
    return function() {
      this.num *= 4;
      num + =20;
      console.log(num);
    }
  })(num)
};
var fn = obj.fn;
fn(); // ->65
obj.fn(); // ->85
console.log(window.num, obj.num) // ->240, 120

上面代码使用堆栈图来描述,如下,首先正方形代表栈内存(函数执行环境,context),圆边方形代表堆内存(用来存放字符串)。

JavaScript this在函数中的指向及实例详解

第一步,形成一个js执行环境,window作用域,首先预解释(声明var,声明+定义function);

第二步,代码由上往下执行,num = 20, obj = 引用数据类型(数据存在堆内存里面)

第三步,因为obj.fn是立即执行函数,所以形成一个私有作用域A,执行fn里面的函数,因为fn里面的函数返回值为function,return值被外面的obj.fn引用了,这个立即执行函数A作用域不销毁。

第四步,window作用域下面的代码继续往下执行。

四、this实践运用

现在有这样一个需求,要求做一个累加器,每点击一次,就累加1。

var oBtn = document.getElementById("btn");
var spanNum = document.getElementById("spanNum");
// 方法一
// 利用全局作用域不销毁的原理,把需要累加的数字定义为全局变量
var count = 0;
oBtn.onclikc = function() {
  count++;
  spanNuM.innerText = count; 
}
// 弊端:在项目中为了防止全局变量之间的冲突,我们一般是禁止或者减少使用全局变量的
 
// 方法二
// 形成一个不销毁的私有作用域保存我们需要累积的数据
// 1)
(function() {
  var count = 0;
  oBtn.onclick = function() {
    ++count;
    spanNum.innerText = count;
  }
})
// 2)
oBtn.onclick = (function() {
  var count = 0;
  return function() {
    ++count;
    spanNum.innerText = count;
  }
})
// 上面的两种写法都是表达同一个意思
// 弊端:有一个不销毁的私有作用域,占那么一点点内存
 
// 方法三
// 利用innerHTML的方式处理,每点击一次都需要到页面获取最新的值,然后累加,最后把结果放进去
oBtn.onclick = function() {
  ++spanNum.innerHTML; 
}
// 弊端:innerHTML获取的时候本来就需要浏览器去处理,每一次都需要把页面的内存先转化为字符串,然后累加,累加完重新添加回去,当重新添加的时候浏览器需要重现渲染一遍页面。
 
// 方法四
// 利用自定义属性存储(推荐!)
oBtn.count = 0;
oBtn.onclick = function() {
  spanNum.innerTxt = ++this.count;  
}
//注意,这里的count只是对象的一个属性,它既不是全局变量,也不是局部变量哦。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
解决jquery的datepicker的本地化以及Today问题
May 23 Javascript
js判断字符长度及中英文数字等
Mar 19 Javascript
jQuery中toggleClass()方法用法实例
Jan 05 Javascript
Underscore.js 1.3.3 中文注释翻译说明
Jun 25 Javascript
AngularJS+Node.js实现在线聊天室
Aug 28 Javascript
通过原生JS实现为元素添加事件的方法
Nov 23 Javascript
关于微信jssdk实现多图片上传的一点心得分享
Dec 13 Javascript
js实现微博发布小功能
Jan 12 Javascript
微信小程序实现顶部普通选项卡效果(非swiper)
Jun 19 Javascript
Vue项目分环境打包的实现步骤
Apr 02 Javascript
浅谈Webpack4 Tree Shaking 终极优化指南
Nov 18 Javascript
weui上传多图片,压缩,base64编码的示例代码
Jun 22 Javascript
vue循环数组改变点击文字的颜色
Oct 14 #Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
Oct 14 #Javascript
VUE+node(express)实现前后端分离
Oct 13 #Javascript
javascript sort()对数组中的元素进行排序详解
Oct 13 #Javascript
javaScript把其它类型转换为Number类型
Oct 13 #Javascript
js 实现watch监听数据变化的代码
Oct 13 #Javascript
15 分钟掌握vue-next响应式原理
Oct 13 #Javascript
You might like
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
2013/11/07 PHP
一个经典的PHP文件上传类分享
2014/11/18 PHP
PHP判断网络文件是否存在的方法
2015/03/12 PHP
调用WordPress函数统计文章访问量及PHP原生计数器的实现
2016/03/21 PHP
php生成酷炫的四个字符验证码
2016/04/22 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
2019/11/24 PHP
如何用javascript去掉字符串里的所有空格
2007/02/08 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
复制网页内容,粘贴之后自动加上网址的实现方法(脚本之家特别整理)
2014/10/16 Javascript
JavaScript中的toDateString()方法使用详解
2015/06/12 Javascript
浅析JavaScript回调函数应用
2016/05/22 Javascript
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
2017/05/27 Javascript
javascript将list转换成树状结构的实例
2017/09/08 Javascript
JavaScript 保护变量不被随意修改的实现代码
2017/09/27 Javascript
js 公式编辑器 - 自定义匹配规则 - 带提示下拉框 - 动态获取光标像素坐标
2018/01/04 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
2020/08/20 Javascript
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[50:02]完美世界DOTA2联赛PWL S2 Magma vs FTD 第三场 11.29
2020/12/03 DOTA
Ubuntu 16.04 LTS中源码安装Python 3.6.0的方法教程
2016/12/27 Python
python 内置函数filter
2017/06/01 Python
Python subprocess模块详细解读
2018/01/29 Python
python购物车程序简单代码
2018/04/18 Python
python使用sklearn实现决策树的方法示例
2019/09/12 Python
python opencv实现gif图片分解的示例代码
2019/12/13 Python
详解django中Template语言
2020/02/22 Python
Django 用户登陆访问限制实例 @login_required
2020/05/13 Python
Django QuerySet查询集原理及代码实例
2020/06/13 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
详解Canvas 跨域脱坑实践
2018/11/07 HTML / CSS
运动会通讯稿50字
2014/01/30 职场文书
爱情寄语大全
2014/04/09 职场文书
中华魂放飞梦想演讲稿
2014/08/26 职场文书
国情备忘录观后感
2015/06/04 职场文书
SQL IDENTITY_INSERT作用案例详解
2021/08/23 MySQL