call、apply、bind的作用是改变函数运行时this的指向。

如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

函数运行时,有三种调用方法。

方法调用模式

 var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
obj1.fn()//2

this是指obj1这个对象,obj1.fn()实际上是obj1.fn.call(obj1);

函数调用模式

var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
var fn1 = obj1.fn
fn1()//
obj1.fn是一个函数function(){console.log(this.a)},此时fn1就是不带任何修饰的函数调用,function(){console.log(this.a)}.call(undefined)
回调函数也属于函数调用
setTimeout(function() {
console.log(this)//window
function fn(){
console.log(this)//window
}
fn()
}, 0);
构造器调用模式

new一个函数时,背地里会将创建一个连接到prototype成员的新对象,同时this会被绑定到那个新对象上

function Person(name,age){
// 这里的this都指向实例
this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
} var dot = new Person('Dot',2)
dot.sayAge()//

上面的三种方法可以这样理解

obj1.fn()
obj1.fn.call(obj1);//指向当前对象 fn1()
fn1.call(null)//指向window对象 f1(f2)
f1.call(null,f2)//指向新对象

call

call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

var arr = [1, 2, 3, 89, 46]
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//

可以这么理解:

obj1.fn()
obj1.fn.call(obj1); fn1()
fn1.call(null) f1(f2)
f1.call(null,f2)

看一个例子:

var obj = {
message: 'My name is: '
} function getName(firstName, lastName) {
console.log(this.message + firstName + ' ' + lastName)
} getName.call(obj, 'Dot', 'Dolby')

apply

apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。

var arr = [1,2,3,89,46]
var max = Math.max.apply(null,arr)//

可以这么理解:

obj1.fn()
obj1.fn.apply(obj1); fn1()
fn1.apply(null) f1(f2)
f1.apply(null,f2)

是不是觉得和前面写的call用法很像,事实上apply 和 call 的用法几乎相同, 唯一的差别在于:当函数需要传递多个变量时, apply 可以接受一个数组作为参数输入, call 则是接受一系列的单独变量。
看一个例子:

var obj = {
message: 'My name is: '
} function getName(firstName, lastName) {
console.log(this.message + firstName + ' ' + lastName)
} getName.apply(obj, ['Dot', 'Dolby'])// My name is: Dot Dolby

可以看到,obj 是作为函数上下文的对象,函数 getName 中 this 指向了 obj 这个对象。参数 firstName 和 lastName 是放在数组中传入 getName 函数。

call和apply可用来借用别的对象的方法,这里以call()为例:

var Person1  = function () {
this.name = 'Dot';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname(); // Dot

从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。像上面的找一组数中最大值的例子,当然是用apply合理。

和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。

  • bind返回值是函数
var obj = {
name: 'Dot'
} function printName() {
console.log(this.name)
} var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot() // Dot

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。

js中this指向问题(call,apply,bind)的更多相关文章

  1. 使用另一种方式实现js中Function的调用(call/apply/bind)

    在JavaScript中函数的调用可以有多种方式,但更经典的莫过于call和apply.call跟apply都绑定在函数上,他们两个的第一个参数意义相同,传入一个对象,他作为函数的执行环境(实质上是为 ...

  2. 关于js中this指向的理解总结!

    关于js中this指向的理解! this是什么?定义:this是包含它的函数作为方法被调用时所属的对象. 首先,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁 ...

  3. 前端js中this指向及改变this指向的方法

    js中this指向是一个难点,花了很长时间来整理和学习相关的知识点. 一. this this是JS中的关键字, 它始终指向了一个对象, this是一个指针; 参考博文: JavaScript函数中的 ...

  4. JS中this指向的更改

    JS中this指向的更改 JavaScript 中 this 的指向问题 前面已经总结过,但在实际开中, 很多场景都需要改变 this 的指向. 现在我们讨论更改 this 指向的问题. call更改 ...

  5. this指向与call,apply,bind

    this指向与call,apply,bind ❝ 「this」问题对于每个前端同学来说相信都不陌生,在平时开发中也经常能碰到,有时候因为「this」还踩过不少坑,并且「this」问题在面试题中出现的概 ...

  6. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

      前  言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于 ...

  7. js中this指向的三种情况

    js中this指向的几种情况一.全局作用域或者普通函数自执行中this指向全局对象window,普通函数的自执行会进行预编译,然后预编译this的指向是window //全局作用域 console.l ...

  8. 关于js中this指向的总结

    js中this指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下this的指向. 1.在对象中的this对象中的this指向我们创建的对 ...

  9. this的指向问题 call apply bind 中的this

    在函数中this指向谁:     函数中的this指向谁,是由函数被调用的那一刻就确定下来的 平时确定一个函数中的this是谁,我们需要通过调用模式来确定 1. 函数调用模式 this ---> ...

随机推荐

  1. K8s中Pod健康检查源代码分析

    了解k8s中的Liveness和Readiness Liveness: 表明是否容器正在运行.如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略. ...

  2. Android 字体库的使用

    开发Android的人大多都知道,Android里面对字体的支持少得可怜,默认情况下,TextView  的 typeface 属性支持 "Sans","serif&qu ...

  3. python 直接if判断和is not None的区别

    tmpName = ''if tmpName: print tmpName #没有输出if tmpName is not None: print tmpName #有输出,是空行

  4. 如何入门 C++ AMP 教程

    本文告诉大家如何写一个 Helloworld 程序. 首先打开 VisualStudio ,大概现在也没有人还在用 VisualStudio 2013 了,所以我就不需要告诉大家需要用哪个版本的 Vi ...

  5. supersockets服务器配置热更新

    Keywords: 配置,热更新 此功能能够允许你在不重启服务器的前提下更新服务器实例的配置. (仅限1.6.5及其以上版本)

  6. 在 CentOS 7.3 上安装 nginx 服务为例,说明在 Linux 实例中如何检查 TCP 80 端口是否正常工作

    CentOS 7.3 这部分以在 CentOS 7.3 上安装 nginx 服务为例,说明在 Linux 实例中如何检查 TCP 80 端口是否正常工作. 登录 ECS 管理控制台,确认实例所在安全组 ...

  7. Java集合系统

    前言: 要想学习java的集合体系,就必须先了解java的集合框架,总的来说,分为Collection和Map体系. Collection集合框架: Map集合框架: 一. Collection接口 ...

  8. Python--day25--面向对象之封装

    狭义上的封装的例子:(例1)Python就只有两种类型:公有和私有,没有Java中说的那种保护类型 例2: 例3:正常的方法调用私有方法 封装总结:

  9. 洛谷P2719 搞笑世界杯 题解 概率DP入门

    作者:zifeiy 标签:概率DP 题目链接:https://www.luogu.org/problem/P2719 我们设 f[n][m] 用于表示还剩下n张A类票m张B类票时最后两张票相同的概率, ...

  10. Spring Data Jpa一对多单向映射

    /** @author StormMaybin @date 2017-01-17 */ 生命不息,奋斗不止! 一对多映射关系 在JPA中,用@OneToMany来标识一对多的关系.实现一对多的单向关联 ...