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 相关文章推荐
javascript &&和||运算法的另类使用技巧
Nov 28 Javascript
JS链式调用的实现方法
Mar 07 Javascript
js中判断对象是否为空的三种实现方法
Dec 23 Javascript
js仿土豆网带缩略图的焦点图片切换效果实现方法
Feb 23 Javascript
BootStrap glyphicons 字体图标实现方法
May 01 Javascript
js实现移动端编辑添加地址【模仿京东】
Apr 28 Javascript
jQuery动态追加页面数据以及事件委托详解
May 06 jQuery
VUE axios发送跨域请求需要注意的问题
Jul 06 Javascript
基于jquery实现多级菜单效果
Jul 25 jQuery
AngularJS实现注册表单验证功能
Oct 16 Javascript
QQ跳转支付宝并自动领红包脚本(最新)
Jun 22 Javascript
JavaScript最完整的深浅拷贝实现方式详解
Feb 28 Javascript
如何利用@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中使用cURL实现Get和Post请求的方法
2013/03/13 PHP
php中删除数组的第一个元素和最后一个元素的函数
2015/03/07 PHP
codeigniter发送邮件并打印调试信息的方法
2015/03/21 PHP
浅谈PHP接收POST数据方式
2015/06/05 PHP
PHP和MySql中32位和64位的整形范围是多少
2016/02/18 PHP
PHP实现RTX发送消息提醒的实例代码
2017/01/03 PHP
又一个图片自动缩小的JS代码
2007/03/10 Javascript
document.onreadystatechange事件的用法分析
2009/10/17 Javascript
javascript 获取元素位置的快速方法 getBoundingClientRect()
2009/11/26 Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
JS网页图片按比例自适应缩放实现方法
2014/01/15 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
2014/12/08 Javascript
JavaScript获取URL汇总
2015/06/08 Javascript
vue2.0构建单页应用最佳实战
2017/04/01 Javascript
vue中的模态对话框组件实现过程
2018/05/01 Javascript
浅谈VUE单页应用首屏加载速度优化方案
2018/08/28 Javascript
微信小程序自定义组件封装及父子间组件传值的方法
2018/08/28 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
2019/07/19 Javascript
浅谈vue中组件绑定事件时是否加.native
2019/11/09 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
[01:05:12]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS CIS-GAME
2014/05/21 DOTA
python实现决策树C4.5算法详解(在ID3基础上改进)
2017/05/31 Python
Python基于matplotlib实现绘制三维图形功能示例
2018/01/18 Python
tensorflow: variable的值与variable.read_value()的值区别详解
2018/07/30 Python
Python读取Excel表格,并同时画折线图和柱状图的方法
2018/10/14 Python
python并发编程 Process对象的其他属性方法join方法详解
2019/08/20 Python
CSS3 按钮边框动画的实现
2020/11/12 HTML / CSS
Audible英国:有声读物,30天免费试用
2019/10/16 全球购物
类的核心特性有哪些
2014/01/01 面试题
机械专业毕业生自荐信
2013/11/02 职场文书
法制宣传日活动总结
2014/04/29 职场文书
篮球社团活动总结
2014/06/27 职场文书
采购员岗位职责范本
2015/04/07 职场文书
2015年幼师工作总结
2015/04/28 职场文书
CSS中实现动画效果-附案例
2022/02/28 HTML / CSS
Smart 2 车辆代号 HC11 全新谍照曝光
2022/04/21 数码科技