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 相关文章推荐
可缩放Reloaded-一个针对可缩放元素的复用组件
Mar 10 Javascript
javascript中的float运算精度实例分析
Aug 21 Javascript
改进UCHOME的记录发布,增强可访问性用户体验
Jan 17 Javascript
javascript中对Attr(dom中属性)的操作示例讲解
Dec 02 Javascript
js复制网页内容并兼容各主流浏览器的代码
Dec 17 Javascript
原生js实现日期联动
Jan 12 Javascript
js友好的时间返回函数
Aug 24 Javascript
Vue.js 2.0 移动端拍照压缩图片上传预览功能
Mar 06 Javascript
微信小程序 Buffer缓冲区的详解
Jul 06 Javascript
Bootstrap 中data-[*] 属性的整理
Mar 13 Javascript
js使用文档就绪函数动态改变页面内容示例【innerHTML、innerText】
Nov 07 Javascript
el-table-column 内容不自动换行的解决方法
Aug 14 Vue.js
如何利用@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 并发最佳实践代码分享
2012/09/05 PHP
PHP简单留言本功能实现代码
2017/06/09 PHP
PHP实现的迪科斯彻(Dijkstra)最短路径算法实例
2017/09/16 PHP
PHP Swoole异步Redis客户端实现方法示例
2019/10/24 PHP
基于jquery的跨域调用文件
2010/11/19 Javascript
jquery修改网页背景颜色通过css方法实现
2014/06/06 Javascript
js确认删除对话框适用于a标签及submit
2014/07/10 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
2015/11/06 Javascript
分享jQuery网页元素拖拽插件
2020/12/01 Javascript
VUEJS实战之利用laypage插件实现分页(3)
2016/06/13 Javascript
微信小程序 获取微信OpenId详解及实例代码
2016/10/31 Javascript
jQuery实现对象转为url参数的方法
2017/01/11 Javascript
Angular2 自定义validators的实现方法
2017/07/05 Javascript
详解PHP后期静态绑定分析与应用
2018/03/21 Javascript
JS封装的模仿qq右下角消息弹窗功能示例
2018/08/22 Javascript
Vuejs+vue-router打包+Nginx配置的实例
2018/09/20 Javascript
vue数据操作之点击事件实现num加减功能示例
2019/01/19 Javascript
微信小程序时间戳转日期的详解
2019/04/30 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
2020/05/10 Javascript
使用Python标准库中的wave模块绘制乐谱的简单教程
2015/03/30 Python
Python 递归函数详解及实例
2016/12/27 Python
python中matplotlib实现最小二乘法拟合的过程详解
2017/07/11 Python
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
python实现微信自动回复功能
2018/04/11 Python
浅谈numpy数组中冒号和负号的含义
2018/04/18 Python
Python中的Django基本命令实例详解
2018/07/15 Python
selenium+python自动化测试之多窗口切换
2019/01/23 Python
Django中自定义admin Xadmin的实现代码
2019/08/09 Python
tensorboard实现同时显示训练曲线和测试曲线
2020/01/21 Python
Python脚本导出为exe程序的方法
2020/03/25 Python
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
长曲棍球装备:Lacrosse Monkey
2020/12/02 全球购物
初中班主任评语
2014/04/24 职场文书
搞笑爱情保证书
2014/04/29 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
导游词之新疆尼雅遗址
2019/10/16 职场文书