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效率调优经验
Jun 04 Javascript
struts2 jquery 打造无限层次的树
Oct 23 Javascript
javascript break指定标签打破多层循环示例
Jan 20 Javascript
使用CamanJS在Web页面上处理图像的技巧
Aug 18 Javascript
基于jquery实现可定制的web在线富文本编辑器附源码下载
Nov 17 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
Dec 02 Javascript
jQuery实现的超简单点赞效果实例分析
Dec 31 Javascript
JS动态改变浏览器标题的方法
Apr 06 Javascript
值得分享的Bootstrap Table使用教程
Nov 23 Javascript
使用原生js封装的ajax实例(兼容jsonp)
Oct 12 Javascript
初学者AngularJS的环境搭建过程
Oct 27 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
Jul 15 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
杏林同学录(八)
2006/10/09 PHP
解析php类的注册与自动加载
2013/07/05 PHP
php多个文件及图片上传实例详解
2014/11/10 PHP
php过滤所有的空白字符(空格、全角空格、换行等)
2015/10/27 PHP
PHP实现多关键字加亮功能
2016/10/21 PHP
PHP基于array_unique实现二维数组去重
2020/07/14 PHP
javascript SpiderMonkey中的函数序列化如何进行
2012/12/05 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
javascript/jquery获取地址栏url参数的方法
2014/03/05 Javascript
jQuery trigger()方法用法介绍
2015/01/13 Javascript
实例讲解javascript注册事件处理函数
2016/01/09 Javascript
Jquery easyui开启行编辑模式增删改操作
2016/01/14 Javascript
探索Vue.js component内容实现
2016/11/03 Javascript
用Vue.js实现监听属性的变化
2016/11/17 Javascript
DropDownList实现可输入可选择(两种版本可选)
2016/12/07 Javascript
老生常谈的跨域处理
2017/01/11 Javascript
JS实现的五级联动菜单效果完整实例
2017/02/23 Javascript
JavaScript 保护变量不被随意修改的实现代码
2017/09/27 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
js canvas实现二维码和图片合成的海报
2020/11/19 Javascript
详解搭建一个vue-cli的移动端H5开发模板
2020/01/17 Javascript
JS图片懒加载技术实现过程解析
2020/07/27 Javascript
原生JS生成指定位数的验证码
2020/10/28 Javascript
python中列表的含义及用法
2020/05/26 Python
python中对二维列表中一维列表的调用方法
2020/06/07 Python
伦敦鲜花递送:Flower Station
2021/02/03 全球购物
学习自我鉴定
2014/02/01 职场文书
交通安全教育制度
2014/02/02 职场文书
《黄河颂》教学反思
2014/02/07 职场文书
2014年党员加强作风建设思想汇报
2014/09/15 职场文书
党员发展大会主持词
2015/07/03 职场文书
2015暑假实习报告范文
2015/07/13 职场文书
七一表彰大会简报
2015/07/20 职场文书
办公室管理规章制度
2015/08/04 职场文书
python实现批量提取指定文件夹下同类型文件
2021/04/05 Python
Python卷积神经网络图片分类框架详解分析
2021/11/07 Python