
JS面试点- bind / call / apply
发布日期:2021-05-04 17:18:35
浏览次数:22
分类:精选文章
本文共 3710 字,大约阅读时间需要 12 分钟。
bind / call / apply 可用于this的显式绑定
this绑定的是 call,apply,bind 的第一个参数
call()方法
var a = { user: 'zxx', fn: function () { console.log(this.user) // zxx }}var b = a.fnb.call(a)
通过在call方法,第一个参数表示要把b添加到哪个环境中,简单来说,this就会指向那个对象。
call方法除了第一个参数以外还可以添加多个参数,如下
var a = { user: 'zxx', fn: function (x, xx) { console.log(this.user) // zxx console.log(x + xx) // 520 }}var b = a.fn
apply()方法
apply方法和call方法有些相似,它也可以改变this的指向
var a = { user: 'zxx', fn: function () { console.log(this.user) // zxx }}var b = a.fnb.apply(a)
同样apply也可以有多个参数,但是不同的是,第二个参数必须是一个数组,如下:
var a = { user: 'zxx', fn: function (x, xx) { console.log(this.user) // zxx console.log(x + xx) // 520 }}var b = a.fn
bind()方法
bind方法和call、apply方法有些不同,但是不管怎么说它们都可以用来改变this的指向。
先看下面一段代码:
var a = { user:"zxx", fn:function(){ console.log(this.user); }}var b = a.fn;b.bind(a);
我们发现代码没有被打印,对,这就是bind和call、apply方法的不同,实际上bind方法返回的是一个修改过后的函数。不会立即调用,而是将函数返回
var a = { user:"zxx", fn:function(){ console.log(this.user); // zxx }}var b = a.fn;var c = b.bind(a);c();
如果要调用的话必须还要加上()
同样bind也可以有多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的。
var a = { user:"zxx", fn:function(e,d,f){ console.log(this.user); // zxx console.log(e,d,f); // 10 1 2 }}var b = a.fn;var c = b.bind(a,10);c(1,2);
回调函数的中使用bindvar obj = { name: 'zxx'}setTimeout(function () { console.log(this) // Object {name: "zxx"}}.bind(obj), 1000)========var obj = { name: 'zxx'}setTimeout(function () { console.log(this) // Window}, 1000)
如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值在调用时会被忽略,实际应用的是默认绑定规则:
var a = { user:"zxx", fn:function(){ console.log(this); // Window }}var b = a.fn;b.apply(null);
总结:call和apply(参数为数组)都是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别。
bind方法
- 对于普通函数,绑定this指向
- 对于构造函数,要保证原函数的原型对象上的属性不能丢失
Function.prototype.bind = function (context, ...args) { // 异常处理 if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); } // 保存this的值,它代表调用 bind 的函数 var self = this; var fNOP = function () {}; var fbound = function () { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } fNOP.prototype = this.prototype; fbound.prototype = new fNOP(); return fbound;}
也可以这么用 Object.create 来处理原型:
Function.prototype.bind = function (context, ...args) { if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; var fbound = function () { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } fbound.prototype = Object.create(self.prototype); return fbound;}
模拟实现call方法
Function.prototype.call = function (context) { let context = context || window; let fn = Symbol('fn'); context.fn = this; let args = []; for(let i = 1, len = arguments.length; i < len; i++) { args.push('arguments[' + i + ']'); } let result = eval('context.fn(' + args +')'); delete context.fn return result;}
ES6 的语法
Function.prototype.call = function (context, ...args) { let context = context || window; let fn = new Symbol('fn'); context.fn = this; let result = eval('context.fn(...args)'); delete context.fn return result;}
apply方法
Function.prototype.apply = function (context, args) { let context = context || window; context.fn = this; let result = eval('context.fn(...args)'); delete context.fn return result;}
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月14日 11时59分16秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
6 个 Linux 运维典型问题
2021-05-08
oracle无法启动asm实例记录
2021-05-08
取消vim打开文件全是黄色方法
2021-05-08
YAML基础教程
2021-05-08
一个系统部署多个tomcat实例
2021-05-08
HP服务器设置iLO
2021-05-08
Redhat 平台下LVM管理说明
2021-05-08
oracle数据库迁移
2021-05-08
《Dotnet9》系列-开源C# Winform控件库强力推荐
2021-05-08
从头实现一个WPF条形图
2021-05-08
.NET CORE(C#) WPF 重新设计Instagram
2021-05-08
.NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐)
2021-05-08
C# WPF开源控件库:MahApps.Metro
2021-05-08
使用QT实现一个简单的登陆对话框(纯代码实现C++)
2021-05-08
QT :warning LNK4042: 对象被多次指定;已忽略多余的指定
2021-05-08
GLFW 源码 下载-编译-使用/GLAD配置
2021-05-08
针对单个网站的渗透思路
2021-05-08
Typescript 学习笔记六:接口
2021-05-08
拥抱HTML5
2021-05-08