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 相关文章推荐
google地图的路线实现代码
Aug 20 Javascript
JS.findElementById()使用介绍
Sep 21 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
HTML5实现留言和回复页面样式
Jul 22 Javascript
webpack入门必知必会
Jan 16 Javascript
axios向后台传递数组作为参数的方法
Aug 11 Javascript
vue动画打包后失效问题的解决方法
Sep 18 Javascript
layui-laydate时间日历控件使用方法详解
Nov 15 Javascript
vue+elementUI实现表格关键字筛选高亮
Oct 26 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 Javascript
基于vue的tab-list类目切换商品列表组件的示例代码
Feb 14 Javascript
javascript遍历对象的五种方式实例代码
Oct 24 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往windows中添加用户
2006/12/06 PHP
mysql+php分页类(已测)
2008/03/31 PHP
php 上传功能实例代码
2010/04/13 PHP
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
读jQuery之六 缓存数据功能介绍
2011/06/21 Javascript
基于Jquery+Ajax+Json的高效分页实现代码
2011/10/29 Javascript
JavaScript中的立即执行函数表达式介绍
2015/03/15 Javascript
通过bootstrap全面学习less
2016/11/09 Javascript
canvas实现粒子时钟效果
2017/02/06 Javascript
Angular入口组件(entry component)与声明式组件的区别详解
2018/04/09 Javascript
vue 自定义提示框(Toast)组件的实现代码
2018/08/17 Javascript
jQuery序列化form表单数据为JSON对象的实现方法
2018/09/20 jQuery
three.js实现圆柱体
2018/12/30 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
2020/10/29 Javascript
python使用BeautifulSoup分析网页信息的方法
2015/04/04 Python
小米5s微信跳一跳小程序python源码
2018/01/08 Python
分析Python中解析构建数据知识
2018/01/20 Python
对Python中gensim库word2vec的使用详解
2018/05/08 Python
python如何实现单链表的反转
2020/02/10 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
Html5内唤醒百度、高德APP的实现示例
2019/05/20 HTML / CSS
canvas生成带二维码海报的踩坑记录
2019/09/11 HTML / CSS
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
最畅销的视频游戏享受高达90%的折扣:CDKeys
2020/02/10 全球购物
LVMH旗下最大的奢侈品网站平台:24S
2020/05/24 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
幼师专业求职推荐信
2013/11/08 职场文书
护士求职推荐信范文
2013/11/23 职场文书
运动会通讯稿300字
2014/02/02 职场文书
幼儿园教师节感谢信
2015/01/23 职场文书
全国爱牙日活动总结
2015/02/05 职场文书
公司档案管理制度
2015/08/05 职场文书
写好求职信的技巧解密
2019/05/14 职场文书
详解JAVA中的OPTIONAL
2021/06/14 Java/Android
通过Qt连接OpenGauss数据库的详细教程
2021/06/23 PostgreSQL
安装harbor作为docker镜像仓库的问题
2022/06/14 Servers