资讯专栏INFORMATION COLUMN

学习JavaScript之this,call,apply

wenhai.he / 348人阅读

摘要:在全局对象中调用,自然读取的是全局对象的值构造器调用说明作为构造器调用时,指向返回的这个对象。最直观的表现就是,去看一些优秀框架的源代码时,不再是被绕的晕乎乎的。

学习起因:

在之前的JavaScript学习中,this,call,apply总是让我感到迷惑,但是他们的运用又非常的广泛。遂专门花了一天,来弄懂JavaScript的this,call,apply。
中途参考的书籍也很多,以《JavaScript设计模式与开发实践》为主,《JavaScript高级程序设计》、《你不知道的JavaScript》为辅。这三本书对我理解this,call,apply都起了很大的帮助。

this

首先,我们先讲述this。

在《JavaScript设计模式与开发实践》关于this的描述中,我认为有一句话切中了this的核心要点。那就是:

JavaScript的this总是指向一个对象

具体到实际应用中,this的指向又可以分为以下四种:

作为对象的方法调用

作为普通函数调用

构造器调用

apply和call调用

接下来我们去剖析前3点,至于第4点的apply和call调用,会在call和apply部分详细讲解。

1.作为对象的方法调用

说明:作为对象方法调用时,this指向该对象。
举例:

/**
 * 1.作为对象的方法调用
 *
 * 作为对象方法调用时,this指向该对象。
 */

var obj = {
  a: 1,
  getA: function() {
    console.log(this === obj);
    console.log(this.a);
  }
};

obj.getA(); // true , 1
2.作为普通函数调用

说明:作为普通函数调用时,this总是指向全局对象(浏览器中是window)。
举例:

/**
 * 2.作为普通函数调用
 *
 * 不作为对象属性调用时,this必须指向一个对象。那就是全局对象。
 */

window.name = "globalName";

var getName = function() {
  console.log(this.name);
};

getName(); // "globalName"

var myObject = {
  name: "ObjectName",
  getName: function() {
    console.log(this.name)
  }
};

myObject.getName(); // "ObjectName"

// 这里实质上是把function() {console.log(this.name)}
// 这句话赋值给了theName。thisName在全局对象中调用,自然读取的是全局对象的name值
var theName = myObject.getName;

theName(); // "globalName"
3.构造器调用

说明:作为构造器调用时,this指向返回的这个对象。
举例:

/**
 * 3.作为构造器调用
 * 
 * 作为构造器调用时,this指向返回的这个对象。
 */

var myClass = function() {
  this.name = "Lxxyx";
};

var obj = new myClass();

console.log(obj.name); // Lxxyx
console.log(obj) // myClass {name: "Lxxyx"}

但是如果构造函数中手动指定了return其它对象,那么this将不起作用。
如果return的是别的数据类型,则没有问题。

var myClass = function() {
  this.name = "Lxxyx";
  // 加入return时,则返回的是别的对象。this不起作用。
  return {
    name:"ReturnOthers"
  }
};

var obj = new myClass();
console.log(obj.name); // ReturnOthers
Call和Apply

Call和Apply的用途一样。都是用来指定函数体内this的指向。

Call和Apply的区别

Call:第一个参数为this的指向,要传给函数的参数得一个一个的输入。
Apply:第一个参数为this的指向,第二个参数为数组,一次性把所有参数传入。

如果第一个参数为null,则this指向宿主环境,在浏览器中则是window。(多谢评论中一波不是一波的指正)

1.改变this指向

说明:这是call和apply最常用的用途了。用于改变函数体内this的指向。
举例:

var name = "GlobalName"

var func = function() {
  console.log(this.name)
};

func(); // "GlobalName"

var obj = {
  name: "Lxxyx",
  getName: function() {
    console.log(this.name)
  }
};

obj.getName.apply(window) // "GlobalName" 将this指向window
func.apply(obj) // "Lxxyx" 将this指向obj
2.借用其它对象的方法

这儿,我们先以一个立即执行匿名函数做开头:

(function(a, b) {
  console.log(arguments) // 1,2
  // 调用Array的原型方法
  Array.prototype.push.call(arguments, 3);
  console.log(arguments) // 1,2,3
})(1,2)

函数具有arguments属性,而arguments是一个类数组。
但是arguments是不能直接调用数组的方法的,所以我们要用call或者apply来调用Array对象的原型方法。
原理也很容易理解,比如刚才调用的是push方法,而push方法在谷歌的v8引擎中,源代码是这样的:

function ArrayPush() {
  var n = TO_UINT32(this.length); // 被push对象的长度
  var m = % _ArgumentsLength(); // push的参数个数
  for (var i = 0; i < m; i++) {
    this[i + n] = % _Arguments(i); // 复制元素
  }
  this.length = n + m; //修正length属性
  return this.length;
}

它只与this有关,所以只要是类数组对象,都可以调用相关方法去处理。

这部分内容比较复杂,再加上自己水平也不太够。所以推荐有条件的同学去购买相关书籍,或者等我的后续博客文章。

感想

通过对这部分的学习,算是加深了对JavaScript的理解。最直观的表现就是,去看一些优秀框架的源代码时,不再是被this,call,apply,bind绕的晕乎乎的。还是很开心的~

下一段时间,准备深入探索一下日常学习和使用的CSS。毕竟JavaScript学了,HTML和CSS也不能落下。

前端路漫漫,且行且歌。

最后附上本人博客地址和原文链接,希望能与各位多多交流。

Lxxyx的前端乐园
原文链接:寒假前端学习(7)——学习JavaScript之this,call,apply

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78587.html

相关文章

  • 深入浅出JavaScriptcall()、apply()方法

    摘要:的作用在中,方法和方法都是为了改变函数运行时上下文而存在的,换句话说就是为了改变函数体内部的指向。欢迎前端大牛纠正错误,如有错误我会及时改正。 写在前面: 隔了很长时间了,也不知道写点什么。最近一直在研究ES6,一直想写出来的文章能对初学者或者是在学习JS路上有所帮助的。这就是我的初衷。 call、apply的作用 在JavaScript中,call()方法和apply()方法都是为了...

    Cympros 评论0 收藏0
  • javascript 基础 call, apply, bind

    摘要:系统,扎实的语言基础是一个优秀的前端工程师必须具备的。第一个参数为调用函数时的指向,随后的参数则作为函数的参数并调用,也就是。和的区别只有一个,就是它只有两个参数,而且第二个参数为调用函数时的参数构成的数组。 系统,扎实的 javascript 语言基础是一个优秀的前端工程师必须具备的。在看了一些关于 call,apply,bind 的文章后,我还是打算写下这篇总结,原因其实有好几个。...

    xeblog 评论0 收藏0
  • JavaScript进阶模拟new Object过程

    摘要:后续我将推出进阶系列,一方面是一个监督自己学习的一个过程,另一方面也会给看到的童鞋一些启发。第二步链接到原型中现在把构造函数和参数都打印出来了。 原文:https://zhehuaxuan.github.io/... 作者:zhehuaxuan 写在前面的话 前端的入门相对简单,相对于其他方向天花板可能会相对较低。但是在市场上一个优秀的前端依旧是很抢手的。能够站在金字塔上的人往往寥寥...

    chengtao1633 评论0 收藏0
  • 小菊花课堂JavaScript关于this

    摘要:另外,的绑定和函数声明的位置没有任何关系,之取决于函数的调用方式。请看下面代码这样,我们就可以在调用的时候强制把它的绑定到上绑定在传统的面向类语言中,使用初始化类时会调用类中的构造函数。 关于this 上一章我们讲了关于作用域和闭包的相关知识,现在开始新一轮的学习,那就是JavaScript中最复杂的机制之一---this关键字。它是一个很特别的关键字,被自动定义在所有函数的作用域中。...

    CHENGKANG 评论0 收藏0
  • 从Vue源码学习JavaScriptthis instanceof Vue

    摘要:函数的调用有以下几种方式作为对象方法调用,作为函数调用,作为构造函数调用,和使用或调用。并且规范中说明,只有对象实现了方法。使用了回到上面作为构造函数调用第一步创建一个空的对象,。第二步链接该对象即设置该对象的构造函数到另一个对象,即。 在src/core/instance/index.js中 if (process.env.NODE_ENV !== production && !(t...

    付永刚 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<