JS中this的指向以及call、apply的作用


Posted in Javascript onMay 06, 2018

在具体的实际应用中,this 的指向无法在函数定义时确定,而是在函数执行的时候才确定的,根据执行时的环境大致可以分为以下3种:

1、当函数作为普通函数调用时,this 指向全局对象

2、当函数作为对象的方法调用时,this 指向该对象

3、当函数作为构造器调用时,this 指向新创建的对象

示例一:

window.name = 'myname';
function getName() {
  console.log(this.name);
}
getName(); //输出myname

示例二:

var boy = {
  name: 'Bob',
  getName: function() {
    console.log(this.name);
  }
}
boy.getName(); //输出Bob

示例三:

function Boy(name) {
  this.name = name;
}
var boy1 = new Boy('Bob');
console.log(boy1.name); //输出Bob

对于示例三,还有一种特殊情况,就是当构造函数通过 "return" 返回的是一个对象的时候,此次运算的最终结果返回的就是这个对象,而不是新创建的对象,因此 this 在这种情况下并没有什么用。

示例四:

function Boy(name) {
  this.name = name;
  return { //返回一个对象
    name: 'Jack'
  }
}
var boy1 = new Boy('Bob');
console.log(boy1.name); //输出Jack

示例五:

function Boy(name) {
  this.name = name;
  return 1; //返回非对象
}
var boy1 = new Boy('Bob');
console.log(boy1.name); //输出Bob

call 和 apply 的作用

apply 接受两个参数,第一个参数指定了函数体内 this 的指向,第二个参数是一个数组或类数组,用于传递被调用函数的参数列表。

示例一:

function getInfo() {
  console.log(this.name+' like '+arguments[0]+' and '+arguments[1]);
}
var boy1 = {
  name: 'Bob',
  age: 12
}
getInfo.apply(boy1,['sing','swimming']); //输出Bob like sing and swimming

call 传入参数的数量是不固定的,跟 apply 相同的是,第一个参数也是用于指定函数体内 this 的指向,从第二个参数开始往后,每个参数被依次传入被调用函数。

示例二:

function getInfo() {
  console.log(this.name+' like '+arguments[0]+' and '+arguments[1]);
}
var boy1 = {
  name: 'Bob',
  age: 12
}
getInfo.call(boy1,'sing','shopping'); //输出Bob like sing and shopping

此外,大部分高级浏览器还实现了 bind 方法,它与 call 和 apply 的区别在于 bind 只是改变函数内部 this 的指向,但不会立即执行,你需要显示调用它。

示例三:模拟浏览器的 bind 方法

Function.prototype.bind = function(obj){
  var self = this;
  return function(){
    return self.apply(obj,arguments);
  }
};
var obj = {
  name: 'Bob',
  age: 12
};
var func = function(){
  console.log(this.name+' like '+arguments[0]+' and '+arguments[1]);
}.bind(obj);
func('sing','shopping');

丢失的 this

在某些情况下会丢失 this 的指向,此时,我们就需要借助 call、apply 和 bind 来改变 this 的指向问题。

示例一:当 "getName" 方法作为 "boy" 对象的属性调用时,this 指向 "boy" 对象,当另外一个变量引用 "getName" 方法时,因为它是作为普通函数调用,所以 this 指向全局对象window

var boy = {
  name: 'Bob',
  getName: function() {
    console.log(this.name);
  }
}
boy.getName(); //输出Bob
var getBoyName = boy.getName;
getBoyName(); //输出undefined

示例二:即使在函数内部定义的函数,如果它作为普通对象调用,this 同样指向 window 对象

var boy1 = {
  name: 'Bob',
  age: 12,
  getInfo: function() {
    console.log(this.name);
    function getAge() {
      console.log(this.age);
    }
    getAge();
  }
}
boy1.getInfo(); //Bob
        //undefined
Javascript 相关文章推荐
Node.js实战 建立简单的Web服务器
Mar 08 Javascript
火狐textarea输入法的bug的触发及解决
Jul 24 Javascript
Javascript setInterval的两种调用方法(实例讲解)
Nov 29 Javascript
在每个匹配元素的外部插入新元素的方法
Dec 20 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 Javascript
javascript闭包功能与用法实例分析
Apr 06 Javascript
jQuery复合事件结合toggle()方法的用法示例
Jun 10 jQuery
防止页面url缓存中ajax中post请求的处理方法
Oct 10 Javascript
vue将后台数据时间戳转换成日期格式
Jul 31 Javascript
layui问题之模拟table表格中的选中按钮选中事件的方法
Sep 20 Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 Javascript
jQuery实现简单聊天室
Feb 08 jQuery
如何利用@angular/cli V6.0直接开发PWA应用详解
May 06 #Javascript
Less 安装及基本用法
May 05 #Javascript
es6新特性之 class 基本用法解析
May 05 #Javascript
JS同步、异步、延迟加载的方法
May 05 #Javascript
JavaScript生成指定范围随机数和随机序列的方法
May 05 #Javascript
JS文件中加载jquery.js的实例代码
May 05 #jQuery
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
May 05 #Javascript
You might like
php json_encode奇怪问题说明
2011/09/27 PHP
discuz加密解密函数使用方法和中文注释
2014/01/21 PHP
PHP把MSSQL数据导入到MYSQL的方法
2014/12/27 PHP
使用phpQuery获取数组的实例
2017/03/13 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
浏览器解析js生成的html出现样式问题的解决方法
2012/04/16 Javascript
关于jquery input textare 事件绑定及用法学习
2013/04/03 Javascript
Jquery实现视频播放页面的关灯开灯效果
2013/05/27 Javascript
在js文件中如何获取basePath处理js路径问题
2013/07/10 Javascript
基于JQuery的列表拖动排序实现代码
2013/10/01 Javascript
jquery中trigger()无法触发hover事件的解决方法
2015/05/07 Javascript
JavaScript实现简单的tab选项卡切换
2016/01/05 Javascript
JS实现title标题栏文字不间断滚动显示效果
2016/09/07 Javascript
JS实现仿百度文库评分功能
2017/01/12 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
简单介绍react redux的中间件的使用
2018/04/06 Javascript
JavaScript实现数组全排列、去重及求最大值算法示例
2018/07/30 Javascript
如何在vue里添加好看的lottie动画
2018/08/02 Javascript
Vue中 v-if 和v-else-if页面加载出现闪现的问题及解决方法
2018/10/12 Javascript
Javascript异步执行不按顺序解决方案
2020/04/30 Javascript
如何使用gpu.js改善JavaScript的性能
2020/12/01 Javascript
python 判断三个数字中的最大值实例代码
2019/07/24 Python
python threading和multiprocessing模块基本用法实例分析
2019/07/25 Python
python 6种方法实现单例模式
2020/12/15 Python
一款基于css3麻将筛子3D翻转特效的实例教程
2014/12/31 HTML / CSS
会计与审计专业大专生求职信
2013/10/03 职场文书
会计岗位职责
2013/11/08 职场文书
车间调度岗位职责
2013/11/30 职场文书
高三高考决心书
2014/03/11 职场文书
党员创先争优承诺书
2014/03/26 职场文书
学校募捐倡议书
2014/05/14 职场文书
员工趣味活动方案
2014/08/27 职场文书
高一作文之暖冬
2019/11/09 职场文书
Nginx配置并兼容HTTP实现代码解析
2021/03/31 Servers
「女孩的钓鱼慢活」全新版权绘公布
2022/03/21 日漫
疑《守望先锋2》A测截图泄露 或将推出新模式、新界面
2022/04/03 其他游戏