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 相关文章推荐
跟随鼠标旋转的文字
Nov 30 Javascript
javascript 写类方式之五
Jul 05 Javascript
Firefox中使用outerHTML的2种解决方法
Jun 07 Javascript
jQuery控制TR显示隐藏的几种方法
Jun 18 Javascript
简介JavaScript中的unshift()方法的使用
Jun 09 Javascript
node.js回调函数之阻塞调用与非阻塞调用
Nov 13 Javascript
浅谈js里面的InttoStr和StrtoInt
Jun 14 Javascript
求js数组的最大值和最小值的四种方法
Mar 03 Javascript
vue自动化表单实例分析
May 06 Javascript
vue使用websocket的方法实例分析
Jun 22 Javascript
jquery将信息遍历到界面上实例代码
Jan 21 jQuery
vue配置多代理服务接口地址操作
Sep 08 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五种设计模式小结
2011/03/23 PHP
php设计模式 FlyWeight (享元模式)
2011/06/26 PHP
PHPExcel读取Excel文件的实现代码
2011/12/06 PHP
ThinkPHP使用Ueditor的方法详解
2016/05/20 PHP
json简单介绍
2008/06/10 Javascript
JS 弹出层 定位至屏幕居中示例
2014/05/21 Javascript
学习使用bootstrap基本控件(table、form、button)
2016/04/12 Javascript
AngularJS基础 ng-include 指令示例讲解
2016/08/01 Javascript
JS实现页面跳转参数不丢失的方法
2016/11/28 Javascript
js 中文汉字转Unicode、Unicode转中文汉字、ASCII转换Unicode、Unicode转换ASCII、中文转换
2016/12/06 Javascript
为JQuery EasyUI 表单组件增加焦点切换功能的方法
2017/04/13 jQuery
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
从vue源码看props的用法
2019/01/09 Javascript
vue接入腾讯防水墙代码
2019/05/07 Javascript
解决layui的radio属性或别的属性没显示出来的问题
2019/09/26 Javascript
继承行为在 ES5 与 ES6 中的区别详解
2019/12/24 Javascript
微信小程序后端实现授权登录
2020/02/24 Javascript
小程序分享链接onShareAppMessage的具体用法
2020/05/22 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
[03:41]DOTA2上海特锦赛小组赛第三日recap精彩回顾
2016/02/28 DOTA
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
Python中操作mysql的pymysql模块详解
2016/09/13 Python
Python 获取项目根路径的代码
2019/09/27 Python
VS2019+python3.7+opencv4.1+tensorflow1.13配置详解
2020/04/16 Python
Python编写单元测试代码实例
2020/09/10 Python
pandas map(),apply(),applymap()区别解析
2021/02/24 Python
HTML5拖拉上传文件的简单实例
2017/01/11 HTML / CSS
荷兰网上鞋店:Ziengs.nl
2017/01/02 全球购物
护理学毕业生自荐信
2013/10/02 职场文书
幼儿园大班毕业感言
2014/02/06 职场文书
初中生操行评语大全
2014/04/24 职场文书
创先争优活动党员公开承诺书
2014/08/29 职场文书
社区文明创建工作总结2015
2015/04/21 职场文书
企业法人任命书
2015/09/21 职场文书
你离财务总监还有多远?速览CFO的岗位职责
2019/11/18 职场文书
php TP5框架生成二维码链接
2021/04/01 PHP