惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
S
Secure Thoughts
S
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Privacy International News Feed
L
Lohrmann on Cybersecurity
Schneier on Security
Schneier on Security
PCI Perspectives
PCI Perspectives
Google DeepMind News
Google DeepMind News
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Latest news
Latest news
H
Hacker News: Front Page
月光博客
月光博客
Forbes - Security
Forbes - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Security @ Cisco Blogs
WordPress大学
WordPress大学
Recent Commits to openclaw:main
Recent Commits to openclaw:main
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
D
Docker
U
Unit 42
Recorded Future
Recorded Future
Spread Privacy
Spread Privacy
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
Application and Cybersecurity Blog
Application and Cybersecurity Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Heimdal Security Blog
Microsoft Azure Blog
Microsoft Azure Blog
V
Vulnerabilities – Threatpost
Vercel News
Vercel News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog
G
GRAHAM CLULEY
Apple Machine Learning Research
Apple Machine Learning Research
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Blog — PlanetScale
Blog — PlanetScale
博客园 - 三生石上(FineUI控件)
罗磊的独立博客
Help Net Security
Help Net Security
Google Online Security Blog
Google Online Security Blog
S
SegmentFault 最新的问题

博客园 - 骨月枫🍁

使用vLLM部署Qwen/Qwen3.5-35B-A3B-FP8并且在DIFY中调用 记录个人数组、字符串自己常忘记的方法,以及ES常用处理方式 解决webpack vue 项目打包生成的文件,资源文件均404问题 js 复制粘贴功能记录 记录下工作中使用的pdf.js 记录下jplayer的简单demo js 函数节流 用ajax与fetch调用阿里云免费接口 h5启动原生APP总结 mac上安装mongoDb以及简单使用 mac快捷键整理以及node的基本使用 html5视频video积累 整理下PC和移动获取点击、移动坐标的代码和坑 html5 实现简单的上传 canvas基础学习(四) canvas基础学习(三) canvas基础学习(二) canvas基础学习(一) 移动端使用百度分享代码
简要谈谈javascript bind 方法
骨月枫🍁 · 2017-09-03 · via 博客园 - 骨月枫🍁

  最近去参加了场面试,跟面试官聊了很多JS基础上的东西,其中有个问题是谈谈对apply、call、bind的理解和区别。顿时一愣,apply、call我知道,经常用的东西,bind是什么鬼!!!好像见过,也瞅过类似的文章,但是...不记得了...难道和jQuery的事件绑定的bind一样...

  既然不知道,那就整理总结下啰~

一、apply和call

  既然提到提到了这两兄弟,也跟着简单做下知识整理。在javascript中,this的指向是一个经常要处理的问题。比较经典的一个问题就是,document.getElementById太长了,敲着好累好烦,用一个短点的方法,对它进行封装一下,就下面这样,两行代码搞定,多么简单~

<div id="test"></div>
<script>
    var getDom = document.getElementById;
    console.log(getDom("test"))
</script>

但是。。。调用时,系统提示Uncaught TypeError: Illegal invocation 啊..........这是什么鬼错误 !其实这就是this的问题,使用document.getElementById,函数执行时this指向document,但是使用getDom,函数执行时,this指向的是window。而在getElementById在内核实现中又使用了this,so 就报错了啰!!!

正确的封装方式为:(即用apply/call设定下函数调用时的this指向)

<div id="test"></div>
<script>
var getDom = (function(func){
    return function(){
        return func.apply(document , arguments);
    }
})(document.getElementById);
console.log(getDom("test"))
</script>

  总结:apply和call的用法是一致的,就是改变和确定函数执行时的this指向,区别就是apply后一个参数是数组,call后是一堆参数。话不多说,进入正题....

二、bind基本

首先来谈谈它跟apply/call的区别,bind方法返回的是一个函数,不会立即执行,待用()调用时才会执行,而apply/call则是立即执行函数。

MDN的解释是:bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

接下来用demo简单使用下

1、单纯的绑定this

var person1 = {
    name : "sky" ,
    getName : function(){
        return this.name;
    }
}
var person2 = {name : "moon"};
var getName = person1.getName.bind(person2);        //绑定person2作为getName函数执行的this
console.log(getName());            //打印的值为moon

这样用法比较简单

2、传参数的形式

var self = {name : "sky" , age: 26}
var getDescription = function(country , city){
    console.log("my name is " + this.name + " , my age is " + this.age + " , I'am from " + country + " " + city);
}.bind(self , "China");
getDescription("WuHan");            //my name is sky , my age is 26 , I'am from China WuHan

个人感觉,这种就是相当于通过bind方法预设一些参数,比如此时就是预设的country参数,调用时在传递动态的参数,比如这里的WuHan。通过这样的方式绑定this,配合预设参数,灵活程度十分的高

三、bind的使用场景

水平有限,仅谈谈个人。我在多层函数嵌套的代码编写中,喜欢使用var _this = this;来保存上级函数作用域中的this,这样在内嵌的函数中就是可以用_this获取上级作用域的this。如果用bind则可以换一种方式,具体对比如下:

<div id="test1">test1</div>
<div id="test2">test2</div>
<script>
    //旧写法,使用_this保存
    var tool1 = {
        name: "sky1",
        bindEvent: function() {
            var _this = this;
            document.getElementById("test1").addEventListener("click", function() {
                console.log(_this.name)
            }, false)
        }
    }
    //新写法,使用bind绑定
    var tool2 = {
        name: "sky2",
        bindEvent: function() {
            document.getElementById("test2").addEventListener("click", function() {
                console.log(this.name)
            }.bind(this), false)
        }
    }
    tool1.bindEvent();
    tool2.bindEvent();
</script>

怎么说呢,代码看起来更加优美一些把....我是颜值控

四、bind 兼容性

bind方法是ES5中扩展的方法,所以IE6、7、8均不兼容...整个人都不好了

怎么办呢,网上有一堆的兼容资料,我比较喜欢自己造轮子...其实也蛮简单的,就是apply/call的封装使用,学习嘛,循序渐进的来,分成两步,以下均用skyBind方法表示...

1、仅仅实现修改执行环境即this的功能

Function.prototype.skyBind = function(context){
    var func = this;        //就是它!!!这个func就是需要执行,且要绑定context的函数!!!!!!
    return function(){
        return func.apply(context , arguments);            //绑定且执行
    }
}
var person1 = {
    name : "sky" ,
    getName : function(){
        return this.name;
    }
}
var person2 = {name : "moon"};
var getName = person1.getName.skyBind(person2);      
console.log(getName());            //打印的值为moon    

很简单有没有!!!

2、加入传参的功能

Function.prototype.skyBind = function(){
    var func = this  ,    //还是它!!!这个func就是需要执行,且要绑定context的函数!!!!!!
        context = [].shift.call(arguments) ,            //此时传入的参数就不单单有this的指向,还是其他的参数,按规定第一个参数就是执行环境,拿到它
        args = [].slice.call(arguments);                //arguments具有数组的属性,毕竟JS是个弱类型的语言,但是它毕竟不是数组,用这个方法就是把arguments转换成数组,不用slice换成splice或者其他的都行
    return function(){
        /* 绑定且执行,执行函数的参数为两个数组的合并
         * 这里需要解释的是args是bind绑定时传入的参数,比如下面demo中的China,而下面的arguments则是实际调用时传入的参数WuHan
         * */
        return func.apply(context , [].concat(args , [].slice.call(arguments) ));            
    }
}
//demo
var self = {name : "sky" , age: 26}
var getDescription = function(country , city){
    console.log("my name is " + this.name + " , my age is " + this.age + " , I'am from " + country + " " + city);
}.skyBind(self , "China");
getDescription("WuHan");            //my name is sky , my age is 26 , I'am from China WuHan

 搞定!!!