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 相关文章推荐
发现的以前不知道的函数
Sep 19 Javascript
IE8对JS通过属性和数组遍历解析不一样的地方探讨
May 06 Javascript
JS使用for循环遍历Table的所有单元格内容
Aug 21 Javascript
js编写的treeview使用方法
Nov 11 Javascript
JavaScript设计模式之代理模式详解
Jun 09 Javascript
React Native模块之Permissions权限申请的实例相机
Sep 28 Javascript
html中通过JS获取JSON数据并加载的方法
Nov 30 Javascript
vuex 使用文档小结篇
Jan 11 Javascript
移动web开发之touch事件实例详解
Jan 17 Javascript
ant-design-vue 快速避坑指南(推荐)
Jan 21 Javascript
bootstrap-paginator服务器端分页使用方法详解
Feb 13 Javascript
jquery实现轮播图特效
Apr 12 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数组冒泡排序算法实例
2016/05/06 PHP
PHP模块化安装教程
2016/06/01 PHP
redirect_uri参数错误的解决方法(必看)
2017/02/16 PHP
PHP实现验证码校验功能
2017/11/16 PHP
静态图片的十一种滤镜效果--不支持Ie7及非IE浏览器。
2007/03/06 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
2011/05/24 Javascript
javascript实现图片循环渐显播放的方法
2015/02/24 Javascript
jQuery中slideUp 和 slideDown 的点击事件
2015/02/26 Javascript
JavaScript获取网页表单提交方式的方法
2015/04/02 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
详解利用 Vue.js 实现前后端分离的RBAC角色权限管理
2017/09/15 Javascript
vue实现文章内容过长点击阅读全文功能的实例
2017/12/28 Javascript
重新认识vue之事件阻止冒泡的实现
2018/08/02 Javascript
JavaScript多种滤镜算法实现代码实例
2019/12/10 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
JavaScript点击按钮生成4位随机验证码
2021/01/28 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
Python正则表达式非贪婪、多行匹配功能示例
2017/08/08 Python
python 生成器协程运算实例
2017/09/04 Python
python实现数据导出到excel的示例--普通格式
2018/05/03 Python
pycharm 配置远程解释器的方法
2018/10/28 Python
Pytorch中的自动求梯度机制和Variable类实例
2020/02/29 Python
使用PyQt5实现图片查看器的示例代码
2020/04/21 Python
Python网页解析器使用实例详解
2020/05/30 Python
朗仕(Lab series)英国官网:雅诗兰黛集团男士专属护肤品牌
2017/11/28 全球购物
屈臣氏马来西亚官网:Watsons马来西亚
2019/06/15 全球购物
软件缺陷的分类都有哪些
2014/08/22 面试题
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
应届大学生求职信
2014/07/20 职场文书
四风自我剖析材料思想汇报
2014/10/01 职场文书
家长通知书家长意见
2014/12/30 职场文书
停电通知范文
2015/04/16 职场文书
幼儿园小班开学寄语
2015/05/27 职场文书
王亚平太空授课观后感
2015/06/12 职场文书
2015年民兵整组工作总结
2015/07/24 职场文书
如何在Python中创建二叉树
2021/03/30 Python