call(),apply(),bind() 区别和用法
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])//89
可以这么理解:
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)//89
可以这么理解:
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合理。
bind
和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。
- 参数的使用
function fn(a, b, c) {
console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C'); // A B C
fn1('A', 'B', 'C'); // Dot A B
fn1('B', 'C'); // Dot B C
fn.call(null, 'Dot'); // Dot undefined undefined
call 是把第二个及以后的参数作为 fn 方法的实参传进去,而 fn1 方法的实参实则是在 bind 中参数的基础上再往后排。
有时候我们也用bind方法实现函数珂里化,以下是一个简单的示例:
var add = function(x) {
return function(y) {
return x + y;
};
};
var increment = add(1);
var addTen = add(10);
increment(2);
// 3
addTen(2);
// 12
在低版本浏览器没有 bind 方法,我们也可以自己实现一个。
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // 保存原函数
context = [].shift.call(arguments), // 保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
}
}
应用场景
- 求数组中的最大和最小值
var arr = [1,2,3,89,46]
var max = Math.max.apply(null,arr)//89
var min = Math.min.apply(null,arr)//1
- 将类数组转化为数组
var trueArr = Array.prototype.slice.call(arrayLike)
- 数组追加
var arr1 = [1,2,3];
var arr2 = [4,5,6];
var total = [].push.apply(arr1, arr2);//6
// arr1 [1, 2, 3, 4, 5, 6]
// arr2 [4,5,6]
- 判断变量类型
function isArray(obj){
return Object.prototype.toString.call(obj) == '[object Array]';
}
isArray([]) // true
isArray('dot') // false
- 利用call和apply做继承
function Person(name,age){
// 这里的this都指向实例
this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
function Female(){
Person.apply(this,arguments)//将父元素所有方法在这里执行一遍就继承了
}
var dot = new Female('Dot',2)
- 使用 log 代理 console.log
function log(){
console.log.apply(console, arguments);
}
// 当然也有更方便的 var log = console.log()
总结
call、apply和bind函数存在的区别:
bind返回对应函数, 便于稍后调用; apply, call则是立即调用。
除此外, 在 ES6 的箭头函数下, call 和 apply 将失效, 对于箭头函数来说:
- 箭头函数体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象;所以不需要类似于
var _this = this这种丑陋的写法 - 箭头函数不可以当作构造函数,也就是说不可以使用 new 命令, 否则会抛出一个错误
call(),apply(),bind() 区别和用法的更多相关文章
- call, apply, bind 区别
#call, apply, bind 区别及模拟实现call apply bind 三者都可以用来改变this的指向,但是在用法上略有不同 首先说一下call和apply的区别 call和apply ...
- SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)
先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...
- call apply bind 区别?
call apply bind 区别? 例:定义一个计算器,没绑定bind的为公共计算器,call可以调用,绑定bind的为私人计算器,别人调用不了, //ps:用bind绑定的call强制作借用不好 ...
- apply、call、bind区别、用法
apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向): 如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是 ...
- js中的call,apply,bind区别
在JavaScript中,call.apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向. call.apply.bind方法的共同点和区别:app ...
- SQLServer连接查询之Cross Apply和Outer Apply的区别及用法
https://blog.csdn.net/wikey_zhang/article/details/77480118 先简单了解下cross apply的语法以及会产生什么样的结果集吧! 示例表: S ...
- Javascript中call和apply的区别和用法
JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别.其实就是更改对象的内部指针,即改变对象的this指向的内容.这在面向对象的js编程过程中有时是很有用的.call ...
- js 中arguments,call,apply,bind的使用
//对于 arguments和this, 每个函数都有自己独有的arguments和this, 且不进行链式查找 //arguments是什么? //答:1:arguments是收到的实参副本 //2 ...
- 一个简单的例子让你很轻松地明白JavaScript中apply、call、bind三者的用法及区别
JavaScript中apply.call.bind三者的用法及区别 引言 正文 一.apply.call.bind的共同用法 二. apply 三. call 四. bind 五.其他应用场景 六. ...
随机推荐
- chrome Provisional headers are shown错误提示(转载)
今天开发时遇到了一个问题,由于要做一个支付等待页,大概的意思就是点击支付之后,跳出来一个页面,告知用户正在跳转到支付页面.这个时候问题来了,指鹤要做的这个静态支付等待页中有图片,而为了要让这个静态页面 ...
- 国外程序员整理的 PHP 资源大全
原文:http://blog.jobbole.com/82908/ ziadoz 在 Github 发起维护的一个 PHP 资源列表,内容包括:库.框架.模板.安全.代码分析.日志.第三方库.配置工具 ...
- 从头学pytorch(十三):使用GPU做计算
GPU计算 默认情况下,pytorch将数据保存在内存,而不是显存. 查看显卡信息 nvidia-smi 我的机器输出如下: Fri Jan 3 16:20:51 2020 +------------ ...
- Java ASM学习(2)
1.编译后的方法区,其中存储的代码都是一些字节码指令 2.Java虚拟机执行模型: java代码是在一个线程内部执行,每个线程都有自己的执行栈,栈由帧组成,每个帧表示一个方法的调用,每调用一个方法,都 ...
- dotnetcore配置框架简介
一.前言 配置的本质就是字符串的键值对,微软的一系列接口其实就是对这些键值对字符串的抽象. 二.基本类型 2.1.Nuget包 Microsoft.Extensions.Configuration.A ...
- js中的this指针的用法
首先看下面代码: function funcA() { this.name = "hello"; console.log(this.name); this.show = funct ...
- Rancher流水线配置文档
2019独角兽企业重金招聘Python工程师标准>>> 一.概述 Rancher流水线从逻辑上可以分为两部分,即CI和CD. CI,可分化为克隆代码.代码打包.发布镜像三部分. CD ...
- (转)mysql数据库表名批量修改大小写
由于不用服务器对mysql的表名的大小写敏感要求不一致,经常在出现线上的数据库down到了本地不能运行的情况,贴出一段代码用来批量修改数据库表名大小写. DELIMITER // DROP PROCE ...
- 翻译 - Kafka Streams 介绍(一)
2019独角兽企业重金招聘Python工程师标准>>> 资料 [原文地址](http://kafka.apache.org/11/documentation/streams/) 正文 ...
- App 自动化环境搭建
1.安装 Appium-desktop 工具 下载地址:https://github.com/appium/appium-desktop/releases 2.安装 Android 环境 安装 JDK ...