0

0

javascript中call apply 与 bind方法详解_基础知识

php中文网

php中文网

发布时间:2016-05-16 15:11:25

|

1816人浏览过

|

来源于php中文网

原创

javascript中,call、apply和bind是function对象自带的三个方法,本文将通过几个场景的应用,来详细理解三个方法。

call()

call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法。

当调用一个函数时,可以赋值一个不同的 this 对象。this 引用当前对象,即 call 方法的第一个参数。

通过 call 方法,你可以在一个对象上借用另一个对象上的方法,比如Object.prototype.toString.call([]),就是一个Array对象借用了Object对象上的方法。

语法 fun.call(thisArg[, arg1[, arg2[, ...]]])
thisArg
在fun函数运行时指定的this值。需要注意的是下面几种情况

(1)不传,或者传null,undefined, 函数中的this指向window对象
(2)传递另一个函数的函数名,函数中的this指向这个函数的引用,并不一定是该函数执行时真正的this值
(3)值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象,如 String、Number、Boolean
(4)传递一个对象,函数中的this指向这个对象

arg1, arg2, ...
指定的参数列表。

例子
初级应用例子

function a(){
 //输出函数a中的this对象
 console.log(this); 
}
//定义函数b
function b(){} 

var obj = {name:'这是一个屌丝'}; //定义对象obj
a.call(); //window
a.call(null); //window
a.call(undefined);//window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b);// function b(){}
a.call(obj); //Object

使用call方法调用匿名函数并且指定上下文的this

立即学习Java免费学习笔记(深入)”;

在下面的例子中,当调用 greet 方法的时候,该方法的 this 值会绑定到 i对象。

function greet() {
 var reply = [this.person, '是一个轻量的', this.role].join(' ');
 console.log(reply);
}

var i = {function greet() {
 var reply = [this.person, '是一个轻量的', this.role].join(' ');
 console.log(reply);
}

var i = {
 person: 'JSLite.io', role: 'Javascript 库。'
};

greet.call(i); 
// JSLite.io 是一个轻量的 Javascript 库。


 person: 'JSLite.io', role: 'Javascript 库。'
};

greet.call(i); 
// JSLite.io 是一个轻量的 Javascript 库。

使用call方法调用匿名函数

在下例中的for循环体内,我们创建了一个匿名函数,然后通过调用该函数的call方法,将每个数组元素作为指定的this值执行了那个匿名函数。这个匿名函数的主要目的是给每个数组元素对象添加一个print方法,这个print方法可以打印出各元素在数组中的正确索引号。当然,这里不是必须得让数组元素作为this值传入那个匿名函数(普通参数就可以),目的是为了演示call的用法。

var animals = [
 {species: 'Lion', name: 'King'},
 {species: 'Whale', name: 'Fail'}
];

for (var i = 0; i < animals.length; i++) {
 (function (i) { 
 this.print = function () { 
  console.log('#' + i + ' ' + this.species + ': ' + this.name); 
 } 
 this.print();
 }).call(animals[i], i);
}
//#0 Lion: King
//#1 Whale: Fail

使用call方法调用函数传参数

var a = {
 name:'JSLite.io', //定义a的属性
 say:function(){ //定义a的方法
  console.log("Hi,I'm function a!");
 }
};
function b(name){
 console.log("Post params: "+ name);
 console.log("I'm "+ this.name);
 this.say();
}

b.call(a,'test');
//Post params: test
//I'm onepixel
//I'm function a!

apply()

语法与 call() 方法的语法几乎完全相同,唯一的区别在于,apply的第二个参数必须是一个包含多个参数的数组(或类数组对象)。apply的这个特性很重要,

在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。

语法:fun.apply(thisArg[, argsArray])
注意: 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。

参数
thisArg

同上call 的thisArg参数。

argsArray

一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

LALALAND
LALALAND

AI驱动的时尚服装设计平台

下载

例子

function jsy(x,y,z){
 console.log(x,y,z);
}

jsy.apply(null,[1,2,3]); 
// 1 2 3

使用apply来链接构造器的例子

你可以使用apply来给一个对象链接构造器,类似于Java. 在接下来的例子中我们会创建一个叫做construct的全局的Function函数,来使你能够在构造器中使用一个类数组对象而非参数列表。

Function.prototype.construct = function(aArgs) {
 var fConstructor = this, 
 fNewConstr = function() { 
 fConstructor.apply(this, aArgs); 
 };
 fNewConstr.prototype = fConstructor.prototype;
 return new fNewConstr();
};
function MyConstructor () {
 for (var nProp = 0; nProp < arguments.length; nProp++) {
  console.log(arguments,this)
  this["property" + nProp] = arguments[nProp];
 }
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);    // logs "Hello world!"
console.log(myInstance instanceof MyConstructor); // logs "true"
console.log(myInstance.constructor);    // logs "MyConstructor"

使用apply和内置函数

聪明的apply用法允许你在某些本来需要写成遍历数组变量的任务中使用内建的函数。在接下里的例子中我们会使用Math.max/Math.min来找出一个数组中的最大/最小值。

//里面有最大最小数字值的一个数组对象
var numbers = [5, 6, 2, 3, 7];

/* 使用 Math.min/Math.max 在 apply 中应用 */
var max = Math.max.apply(null, numbers);
// 一般情况是用 Math.max(5, 6, ..) 或者 Math.max(numbers[0], ...) 来找最大值
var min = Math.min.apply(null, numbers);

//通常情况我们会这样来找到数字的最大或者最小值
//比对上面的栗子,是不是下面的看起来没有上面的舒服呢?
max = -Infinity, min = +Infinity;
for (var i = 0; i < numbers.length; i++) {
 if (numbers[i] > max)
 max = numbers[i];
 if (numbers[i] < min) 
 min = numbers[i];
}

参数数组切块后循环传入

function minOfArray(arr) {
 var min = Infinity;
 var QUANTUM = 32768;

 for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
 var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
 console.log(submin, min)
 min = Math.min(submin, min);
 }

 return min;
}

var min = minOfArray([5, 6, 2, 3, 7]);


bind

bind() 函数会创建一个新函数(称为绑定函数)

bind是ES5新增的一个方法
传参和call或apply类似
不会执行对应的函数,call或apply会自动执行对应的函数
返回对函数的引用
语法 fun.bind(thisArg[, arg1[, arg2[, ...]]])

下面例子:当点击网页时,EventClick被触发执行,输出JSLite.io p1 p2, 说明EventClick中的this被bind改变成了obj对象。如果你将EventClick.bind(obj,'p1','p2') 变成 EventClick.call(obj,'p1','p2') 的话,页面会直接输出 JSLite.io p1 p2

var obj = {name:'JSLite.io'};
/**
 * 给document添加click事件监听,并绑定EventClick函数
 * 通过bind方法设置EventClick的this为obj,并传递参数p1,p2
 */
document.addEventListener('click',EventClick.bind(obj,'p1','p2'),false);
//当点击网页时触发并执行
function EventClick(a,b){
 console.log(
   this.name, //JSLite.io
   a, //p1
   b //p2
 )
}
// JSLite.io p1 p2

兼容

if (!Function.prototype.bind) {
 Function.prototype.bind = function (oThis) {
 if (typeof this !== "function") {
  // closest thing possible to the ECMAScript 5
  // internal IsCallable function
  throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
 }

 var aArgs = Array.prototype.slice.call(arguments, 1), 
  fToBind = this, // this在这里指向的是目标函数
  fNOP = function () {},
  fBound = function () {
   return fToBind.apply(this instanceof fNOP
     ? this //此时的this就是new出的obj
     : oThis || this,//如果传递的oThis无效,就将fBound的调用者作为this
    
    //将通过bind传递的参数和调用时传递的参数进行合并,并作为最终的参数传递
    aArgs.concat(Array.prototype.slice.call(arguments)));
  };
 fNOP.prototype = this.prototype;
 //将目标函数的原型对象拷贝到新函数中,因为目标函数有可能被当作构造函数使用
 fBound.prototype = new fNOP();
 //返回fBond的引用,由外部按需调用
 return fBound;
 };
}

兼容例子来源于:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility

应用场景:继承

function Animal(name,weight){
 this.name = name;
 this.weight = weight;
}
function Cat(){
 // 在call中将this作为thisArgs参数传递
 // Animal方法中的this就指向了Cat中的this
 // 所以Animal中的this指向的就是cat对象
 // 在Animal中定义了name和weight属性,就相当于在cat中定义了这些属性
 // cat对象便拥有了Animal中定义的属性,从而达到了继承的目的
 Animal.call(this,'cat','50');
 //Animal.apply(this,['cat','50']);
 this.say = function(){
  console.log("I am " + this.name+",my weight is " + this.weight);
 }
}
//当通过new运算符产生了cat时,Cat中的this就指向了cat对象
var cat = new Cat();
cat.say();
//输出=> I am cat,my weight is 50

原型扩展

在原型函数上扩展和自定义方法,从而不污染原生函数。例如:我们在 Array 上扩展一个 forEach

function test(){
 // 检测arguments是否为Array的实例
 console.log(
  arguments instanceof Array, //false
  Array.isArray(arguments) //false
 );
 // 判断arguments是否有forEach方法
 console.log(arguments.forEach); 
 // undefined
 // 将数组中的forEach应用到arguments上
 Array.prototype.forEach.call(arguments,function(item){
  console.log(item); // 1 2 3 4
 });
}
test(1,2,3,4);

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

1

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

1

2026.01.28

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

23

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

120

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

50

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

191

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

7

2026.01.26

windows安全中心怎么关闭 windows安全中心怎么执行操作
windows安全中心怎么关闭 windows安全中心怎么执行操作

关闭Windows安全中心(Windows Defender)可通过系统设置暂时关闭,或使用组策略/注册表永久关闭。最简单的方法是:进入设置 > 隐私和安全性 > Windows安全中心 > 病毒和威胁防护 > 管理设置,将实时保护等选项关闭。

7

2026.01.26

2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】
2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】

铁路12306提供起售时间查询、起售提醒、购票预填、候补购票及误购限时免费退票五项服务,并强调官方渠道唯一性与信息安全。

183

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号