您的位置:新葡亰496net > 新葡亰官网 > 新葡亰496net:这段js代码得拯救你多少时间,深入

新葡亰496net:这段js代码得拯救你多少时间,深入

发布时间:2019-06-23 00:06编辑:新葡亰官网浏览(175)

    至于 bind 你大概需求领悟的知识点以及选取情状

    2016/08/18 · JavaScript · bind

    本文笔者: 伯乐在线 - 韩子迟 。未经作者许可,禁止转发!
    招待加入伯乐在线 专辑作者。

    不看不清楚,一看吓一跳,已经全部五个月未有立异 underscore 源码解读类别文章了。前面我们已经成功了 Object ,Array,Collection 上的恢弘方法的源码剖判,本文先导来解读 Function 上的恢宏方法。

    完整的 underscore 源码解读连串小说请移步 ,以为还阔以的话,给个 star 鼓励下楼主呗 ^_^

    这篇小说主要介绍了Javascript Function.prototype.bind详细解析的有关资料,须求的对象可以参见下

    JavaScript 深远之bind的上行下效完结

    2017/05/26 · JavaScript · bind

    原稿出处: 冴羽   

    javascript中bind函数的机能实例介绍,javascriptbind

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <style>
    button {background-color:#0f0;}
    </style>
    </head>
    <body>
    <button id="button"> 按钮 </button>
    <input type="text">
    <script>
    var button = document.getElementById("button");
    button.onclick = function() {
    alert(this.id); // 弹出button
    };
    //可以看出上下文的this 为button
    </script>
    </body>
    </html>
    

    那会儿加入bind

    复制代码 代码如下:

     var text = document.getElementById("text");
     var button = document.getElementById("button");
     button.onclick = function() {
     alert(this.id); // 弹出button
     }.bind(text);
     //能够见到上下文的this 为button

    那会儿会意识this改换为text

    函数字面量里也适用,指标是保持内外指向(this)不改变。

    var obj = {
    color: "#ccc", 
    element: document.getElementById('text'),
    events: function() {
    document.getElementById("button").addEventListener("click", function(e) {
    console.log(this);
    this.element.style.color = this.color;
    }.bind(this))
    return this;
    },
    init: function() {
    this.events();
    }
    };
    obj.init();
    

    那会儿点击按键text里的字会变色。可知this不为button而是obj。

    bind()的不二等秘书籍在ie,6,7,第88中学不适用,须求扩充通过扩张Function prototype能够达成此格局。

    if (!Function.prototype.bind) {
    
    Function.prototype.bind = function(obj) {
    var slice = [].slice, args = slice.call(arguments, 1), self = this, nop = function() {
    }, bound = function() {
    return self.apply(this instanceof nop ? this : (obj || {}),
    args.concat(slice.call(arguments)));
    };
    
    nop.prototype = self.prototype;
    
    bound.prototype = new nop();
    
    return bound;
    };
    }
    

    这时候得以看来ie6,7,8中也支持bind()。

    复制代码 代码如下:

    slice = Array.prototype.slice,

    array = Array.prototype.slice.call( array, 0 );

    将临近数组转换为数组

     

    bind 简介

    Ok,明天要讲的就是 bind。关于 bind,可以先活动楼主从前写的篇章 ECMAScript 5(ES5) 中 bind 方法简单介绍备忘,有个大旨的概念。

    bind() 方法会创立贰个新函数,当以此新函数被调用时,它的 this 值是传递给 bind() 的第贰个参数, 它的参数是 bind() 的别样参数和其原来的参数。

    语法是那样样子的:

    fun.bind(thisArg[, arg1[, arg2[, ...]]])

    1
    fun.bind(thisArg[, arg1[, arg2[, ...]]])
    • thisArg 当绑定函数被调用时,该参数会作为原函数运维时的 this 指向。当使用 new 操作符调用绑定函数时,该参数无效。
    • arg1, arg2, … (可选)当绑定函数被调用时,那个参数加上绑定函数本身的参数会服从顺序作为原函数运维时的参数。

      Function.prototype.bind分析

    bind

    一句话介绍 bind:

    bind() 方法会创设四个新函数。当那一个新函数被调用时,bind() 的率先个参数将用作它运转时的 this,之后的一系列参数将会在传递的实参前流传作为它的参数。(来自于 MDN )

    通过大家得以率先得出 bind 函数的两日性状:

    1. 归来叁个函数
    2. 能够流传参数

    javascript bind的用法

    javascript的bind

    bind首固然为着改动函数内部的this指向,那么些是在ECMA5事后进入的,所以IE8一下的浏览器不匡助

    bind方法会创造三个新函数,称为绑定函数.当调用那些绑定函数时,绑定函数会以创办它时传入bind方法的率先个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运维时本身的参数依照顺序作为原函数的参数来调用原函数.

    能够看这段实例:
    var logger = { x: 0, updateCount: function(){ this.x ; console.log(this.x); }} // 上面两段代码的兑现是一致的 document.querySelector('button').add伊夫ntListener('click', function(){ logger.updateCount();}); //用这种艺术让代码越来越精简,当然那只是bind的一种情形document.querySelector('button').add伊芙ntListener('click', logger.updateCount.bind(logger));  

    1.利用案例:

    参数

    bind 的首先个参数会作为原函数运维时的 this 指向,非常少说;而第一个起来的参数是可选的,当绑定函数被调用时,那一个参数加上绑定函数本身的参数会遵守顺序作为原函数运转时的参数。怎么通晓?

    function fn(a, b, c) { return a b c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30); // 60

    1
    2
    3
    4
    5
    6
    function fn(a, b, c) {
      return a b c;
    }
     
    var _fn = fn.bind(null, 10);
    var ans = _fn(20, 30); // 60

    fn 函数必要七个参数,_fn 函数将 10 作为默许的第一个参数,所以只须求传入多个参数就可以,假诺您十分大心传入了四个参数,放心,也只会取前两个。

    function fn(a, b, c) { return a b c; } var _fn = fn.bind(null, 10); var ans = _fn(20, 30, 40); // 60

    1
    2
    3
    4
    5
    6
    function fn(a, b, c) {
      return a b c;
    }
     
    var _fn = fn.bind(null, 10);
    var ans = _fn(20, 30, 40); // 60

    那有吗用吧?假若某个函数,前多少个参数已经 “钦定” 了,大家便能够用 bind 重临三个新的函数。也正是说,bind() 能使三个函数具有预设的开始参数。那一个参数(假使局地话)作为 bind() 的第一个参数跟在 this 前面,之后它们会被插入到对象函数的参数列表的初始地点,传递给绑定函数的参数会跟在它们的末尾。

    function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3] // Create a function with a preset leading argument var leadingThirtysevenList = list.bind(undefined, 37); var list2 = leadingThirtysevenList(); // [37] var list3 = leadingThirtysevenList(1, 2, 3); // [新葡亰496net:这段js代码得拯救你多少时间,深入之bind的模拟实现。37, 1, 2, 3]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function list() {
      return Array.prototype.slice.call(arguments);
    }
     
    var list1 = list(1, 2, 3); // [1, 2, 3]
     
    // Create a function with a preset leading argument
    var leadingThirtysevenList = list.bind(undefined, 37);
     
    var list2 = leadingThirtysevenList(); // [37]
    var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

    bind()方法会创设叁个新的函数,成为绑定函数。当调用那个绑定函数时,绑定函数会以创办它时传出的第三个参数作为this,传入bind()方法的第贰个以及随后的参数加上绑定函数运营时自己的参数依据顺序作为原函数的参数来调取原函数。

    回来函数的模仿完结

    从第二个特征发轫,我们举例:

    var foo = { value: 1 }; function bar() { console.log(this.value); } // 再次回到了贰个函数 var bindFoo = bar.bind(foo); bindFoo(); // 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var foo = {
        value: 1
    };
     
    function bar() {
        console.log(this.value);
    }
     
    // 返回了一个函数
    var bindFoo = bar.bind(foo);
     
    bindFoo(); // 1

    关于内定 this 的指向,我们得以采纳 call 或然 apply 贯彻,关于 call 和 apply 的模仿完结,能够查阅《JavaScript深切之call和apply的画虎不成反类犬达成》。我们来写第一版的代码:

    // 第一版 Function.prototype.bind2 = function (context) { var self = this; return function () { self.apply(context); } }

    1
    2
    3
    4
    5
    6
    7
    8
    // 第一版
    Function.prototype.bind2 = function (context) {
        var self = this;
        return function () {
            self.apply(context);
        }
     
    }

    javascript:对于Functionprototypebind()这些方法

    Function.prototype.bind=function(thisArg){ var fn=this, slice=Array.prototype.slice, args=slice.call(arguments,1);//arguments1 var a1 = arguments; return function(){ alert(a1 == arguments);// 判定是或不是为同贰个 return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2 }};((function(){}).bind())(2);// 总是alert出false不是。第三个arguments是只thisArg,第二个则是指再次回到的老大函数的arguments。

    Function.prototype.bind=function(thisArg){ var fn=this, slice=Array.prototype.slice, args=slice.call(arguments,1);//arguments1 alert(arguments[0]);// alert出1 return function(){ alert(arguments[0]);// alert出2 return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2 }};((function(){}).bind(1))(2);  

    !DOCTYPE htmlhtmlheadmeta charset="utf-8"stylebutton {background-color:#0f0;}/style/headbodybutton id="button" 按钮...

      

    new

    应用 bind 重回的结果如故个 function,是个 function 就可以被 new 运算符调用,那么结果吧?规范中说的很明亮了,当使用 new 操作符调用绑定函数时,bind 的率先个参数无效。

    function Person(name, age) { this.name = name; this.age = age; } var _Person = Person.bind({}); var p = new _Person('hanzichi', 30); // Person {name: "hanzichi", age: 30}

    1
    2
    3
    4
    5
    6
    7
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
     
    var _Person = Person.bind({});
    var p = new _Person('hanzichi', 30); // Person {name: "hanzichi", age: 30}

    诚如大家不会去那样用,不过只要要写个 bind 的 polyfill(),依旧必要思量用 new 调用的气象。

    大家也能够安装暗中同意值(仿照效法上一小节),原先提供的那多少个参数还是会被放置到构造函数调用的前方。

    function Person(name, age) { this.name = name; this.age = age; } var _Person = Person.bind(null, 'hanzichi'); var p = new _Person(30); // Person {name: "hanzichi", age: 30}

    1
    2
    3
    4
    5
    6
    7
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
     
    var _Person = Person.bind(null, 'hanzichi');
    var p = new _Person(30); // Person {name: "hanzichi", age: 30}

          实际行使中大家常常会蒙受那样的主题材料:

    传参的模仿完结

    接下去看第二点,能够流传参数。这几个就有一些令人费解了,笔者在 bind 的时候,是还是不是能够传参呢?笔者在实施 bind 重返的函数的时候,可不得以传参呢?让大家看个例子:

    var foo = { value: 1 }; function bar(name, age) { console.log(this.value); console.log(name); console.log(age); } var bindFoo = bar.bind(foo, 'daisy'); bindFoo('18'); // 1 // daisy // 18

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var foo = {
        value: 1
    };
     
    function bar(name, age) {
        console.log(this.value);
        console.log(name);
        console.log(age);
     
    }
     
    var bindFoo = bar.bind(foo, 'daisy');
    bindFoo('18');
    // 1
    // daisy
    // 18

    函数必要传 name 和 age 五个参数,竟然还足以在 bind 的时候,只传一个name,在实践回来的函数的时候,再传另一个参数 age!

    那可如何是好?不急,大家用 arguments 进行拍卖:

    // 第二版 Function.prototype.bind2 = function (context) { var self = this; // 获取bind2函数从第四个参数到结尾七个参数 var args = Array.prototype.slice.call(arguments, 1); return function () { // 今年的arguments是指bind重回的函数字传送入的参数 var bindArgs = Array.prototype.slice.call(arguments); self.apply(context, args.concat(bindArgs)); } }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 第二版
    Function.prototype.bind2 = function (context) {
     
        var self = this;
        // 获取bind2函数从第二个参数到最后一个参数
        var args = Array.prototype.slice.call(arguments, 1);
     
        return function () {
            // 这个时候的arguments是指bind返回的函数传入的参数
            var bindArgs = Array.prototype.slice.call(arguments);
            self.apply(context, args.concat(bindArgs));
        }
     
    }

            var Mouse = function () {

    配合 setTimeout

    什么样时候便于遗失 this 指向?恩,setTimeout 是贰个情景,很轻便把 this 指向 window,当然,setInterval 也是一致。当使用对象的点牛时,须要 this 引用对象,你大概须要显式地把 this 绑定到回调函数以便继续利用对象。

    var canvas = { render: function() { this.update(); this.draw(); }, update: function() { // ... }, draw: function() { // ... } }; window.setInterval(canvas.render, 1000 / 60);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var canvas = {
      render: function() {
        this.update();
        this.draw();
      },
     
      update: function() {
        // ...
      },
     
      draw: function() {
        // ...
      }
    };
     
    window.setInterval(canvas.render, 1000 / 60);

    用 canvas 写特效也许做游戏时日常会赶过类似的标题。上边的代码是有题指标,render 方法中的 this 其实被针对了 window!我们得以用 bind,显式地把 this 绑定到回调函数以便继续行使该对象。

    window.setInterval(canvas.render.bind(canvas), 1000);

    1
    window.setInterval(canvas.render.bind(canvas), 1000);

    好像的情状还大概有 dom 的风浪监听,一相当的大心恐怕 this 就被针对了 dom 成分。能够参照他事他说加以考查下在此之前做 bigrender 时写的这部分代码 。

    var name = "pig";

    构造函数效果的模拟达成

    成功了这两点,最难的某些到啦!因为 bind 还会有叁个特征,就是

    多少个绑定函数也能使用new操作符创设对象:这种作为就好像把原函数当成构造器。提供的 this 值被忽略,同一时间调用时的参数被提须要模拟函数。

    也正是说当 bind 重回的函数作为构造函数的时候,bind 时钦点的 this 值会失效,但传播的参数照旧奏效。比如:

    var value = 2; var foo = { value: 1 }; function bar(name, age) { this.habit = 'shopping'; console.log(this.value); console.log(name); console.log(age); } bar.prototype.friend = 'kevin'; var bindFoo = bar.bind(foo, 'daisy'); var obj = new bindFoo('18'); // undefined // daisy // 18 console.log(obj.habit); console.log(obj.friend); // shopping // kevin

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    var value = 2;
     
    var foo = {
        value: 1
    };
     
    function bar(name, age) {
        this.habit = 'shopping';
        console.log(this.value);
        console.log(name);
        console.log(age);
    }
     
    bar.prototype.friend = 'kevin';
     
    var bindFoo = bar.bind(foo, 'daisy');
     
    var obj = new bindFoo('18');
    // undefined
    // daisy
    // 18
    console.log(obj.habit);
    console.log(obj.friend);
    // shopping
    // kevin

    留意:就算在大局和 foo 中都宣称了 value 值,最终依然重回了 undefind,表达绑定的 this 失效了,若是我们领会 new 的一成不改变完成,就能够知道那个时候的 this 已经针对了 obj。

    (哈哈,作者那是为本身的下一篇文章《JavaScript长远连串之new的依样葫芦落成》打广告)。

    就此大家能够透过修改重临的函数的原型来达成,让大家写一下:

    // 第三版 Function.prototype.bind2 = function (context) { var self = this; var args = Array.prototype.slice.call(arguments, 1); var fbound = function () { var bindArgs = Array.prototype.slice.call(arguments); // 当作为构造函数时,this 指向实例,self 指向绑定函数,因为上面一句 `fbound.prototype = this.prototype;`,已经修改了 fbound.prototype 为 绑定函数的 prototype,此时结果为 true,当结果为 true 的时候,this 指向实例。 // 当作为日常函数时,this 指向 window,self 指向绑定函数,此时结果为 false,当结果为 false 的时候,this 指向绑定的 context。 self.apply(this instanceof self ? this : context, args.concat(bindArgs)); } // 修改再次来到函数的 prototype 为绑定函数的 prototype,实例就足以继续函数的原型中的值 fbound.prototype = this.prototype; return fbound; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 第三版
    Function.prototype.bind2 = function (context) {
        var self = this;
        var args = Array.prototype.slice.call(arguments, 1);
     
        var fbound = function () {
     
            var bindArgs = Array.prototype.slice.call(arguments);
            // 当作为构造函数时,this 指向实例,self 指向绑定函数,因为下面一句 `fbound.prototype = this.prototype;`,已经修改了 fbound.prototype 为 绑定函数的 prototype,此时结果为 true,当结果为 true 的时候,this 指向实例。
            // 当作为普通函数时,this 指向 window,self 指向绑定函数,此时结果为 false,当结果为 false 的时候,this 指向绑定的 context。
            self.apply(this instanceof self ? this : context, args.concat(bindArgs));
        }
        // 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承函数的原型中的值
        fbound.prototype = this.prototype;
        return fbound;
    }

    假使对原型链稍有狐疑,能够查看《JavaScript深切之从原型到原型链》。

                // Look! no that = this!

    tip

    bind 还是能做一些妙趣横生的事体。

    常备来讲,将叁个类数组转为数组,大家会用 slice(ie9- 不补助)。参谋

    var slice = Array.prototype.slice; // slice.apply(arguments); // slice(arguments, 1);

    1
    2
    3
    4
    var slice = Array.prototype.slice;
     
    // slice.apply(arguments);
    // slice(arguments, 1);

    bind 能让调用变的愈发简明。

    // same as "slice" in the previous example var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); // ... slice(arguments); // slice(arguments, 1);

    1
    2
    3
    4
    5
    6
    7
    8
    // same as "slice" in the previous example
    var unboundSlice = Array.prototype.slice;
    var slice = Function.prototype.call.bind(unboundSlice);
     
    // ...
     
    slice(arguments);
    // slice(arguments, 1);

    再举个类似的例证,比如说我们要加多事件到四个节点,for 循环当然未有其余难题,咱们还能 “剽窃” forEach 方法:

    Array.prototype.forEach.call(document.querySelectorAll('input[type="button"]'), function(el){ el.addEventListener('click', fn); });

    1
    2
    3
    Array.prototype.forEach.call(document.querySelectorAll('input[type="button"]'), function(el){
      el.addEventListener('click', fn);
    });

    更进一步,大家得以用 bind 将函数封装的更加好:

    var unboundForEach = Array.prototype.forEach , forEach = Function.prototype.call.bind(unboundForEach); forEach(document.querySelectorAll('input[type="button"]'), function (el) { el.addEventListener('click', fn); });

    1
    2
    3
    4
    5
    6
    var unboundForEach = Array.prototype.forEach
      , forEach = Function.prototype.call.bind(unboundForEach);
     
    forEach(document.querySelectorAll('input[type="button"]'), function (el) {
      el.addEventListener('click', fn);
    });

    一律看似的,我们能够将 x.y(z) 形成 y(x,z) 的款型:

    var obj = { num: 10, getCount: function() { return this.num; } }; var unboundBind = Function.prototype.bind , bind = Function.prototype.call.bind(unboundBind); var getCount = bind(obj.getCount, obj); console.log(getCount()); // 10

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var obj = {
      num: 10,
      getCount: function() {
        return this.num;
      }
    };
     
    var unboundBind = Function.prototype.bind
      , bind = Function.prototype.call.bind(unboundBind);
     
    var getCount = bind(obj.getCount, obj);
    console.log(getCount());  // 10

    再举个栗子。每隔一秒在调控台打印 1-5,看起来是道调查闭包的经文标题。

    for(var i = 1; i <= 5; i ) { !function(i) { setTimeout(function() { console.log(i); }, i * 1000); }(i); }

    1
    2
    3
    4
    5
    6
    7
    for(var i = 1; i <= 5; i ) {
      !function(i) {
        setTimeout(function() {
          console.log(i);
        }, i * 1000);
      }(i);
    }

    ES6 下能用 let

    for(let i = 1; i <= 5; i ) { setTimeout(function() { console.log(i); }, i * 1000); }

    1
    2
    3
    4
    5
    for(let i = 1; i <= 5; i ) {
      setTimeout(function() {
        console.log(i);
      }, i * 1000);
    }

    也可以用 bind,须臾间逼格进步:

    for(var i = 1; i <= 5; i ) { setTimeout(console.log.bind(console, i), i * 1000); }

    1
    2
    3
    for(var i = 1; i <= 5; i ) {
      setTimeout(console.log.bind(console, i), i * 1000);
    }

    function Person(name){

    构造函数效果的优化达成

    只是在那一个写法中,大家直接将 fbound.prototype = this.prototype,大家平昔退换 fbound.prototype 的时候,也会一向改造函数的 prototype。今年,大家可以透过三个空函数来拓展转账:

    // 第四版 Function.prototype.bind2 = function (context) { var self = this; var args = Array.prototype.slice.call(arguments, 1); var fNOP = function () {}; var fbound = function () { var bindArgs = Array.prototype.slice.call(arguments); self.apply(this instanceof self ? this : context, args.concat(bindArgs)); } fNOP.prototype = this.prototype; fbound.prototype = new fNOP(); return fbound; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 第四版
    Function.prototype.bind2 = function (context) {
     
        var self = this;
        var args = Array.prototype.slice.call(arguments, 1);
     
        var fNOP = function () {};
     
        var fbound = function () {
            var bindArgs = Array.prototype.slice.call(arguments);
            self.apply(this instanceof self ? this : context, args.concat(bindArgs));
        }
        fNOP.prototype = this.prototype;
        fbound.prototype = new fNOP();
        return fbound;
     
    }

    到此甘休,大的题材都早已减轻,给自身贰个赞!o( ̄▽ ̄)d

                this.position = [0, 0];

    Read more

    有关 bind 的介绍就到此处,下一篇小说将整合 underscore 来说讲怎么落实三个bind 的 polyfill。

    • Function.prototype.bind()
    • ECMAScript 5(ES5) 中 bind 方法简要介绍备忘
    • Javascript 中的 Bind ,Call 以及 Apply
    • Javascript 中 bind() 方法的运用与完结

    打赏帮忙本人写出更加多好文章,感激!

    打赏我

      this.name = name;

    七个小标题

    接下去管理些未有失常态:

    1.apply 这段代码跟 MDN 上的稍有例外

    在 MDN 普通话版讲 bind 的一步一趋完毕时,apply 这里的代码是:

    self.apply(this instanceof self ? this : context || this, args.concat(bindArgs))

    1
    self.apply(this instanceof self ? this : context || this, args.concat(bindArgs))

    多了七个关于 context 是不是留存的论断,然则这些是不当的!

    例如:

    var value = 2; var foo = { value: 1, bar: bar.bind(null) }; function bar() { console.log(this.value); } foo.bar() // 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var value = 2;
    var foo = {
        value: 1,
        bar: bar.bind(null)
    };
     
    function bar() {
        console.log(this.value);
    }
     
    foo.bar() // 2

    如上代码平常情状下会打字与印刷 2,如果换到了 context || this,这段代码就能够打字与印刷1!

    之所以那边不该张开 context 的判别,我们查看 MDN 同样内容的英文版,就不设有那个论断!

    2.调用 bind 的不是函数怎么做?

    不行,大家要报错!

    if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); }

    1
    2
    3
    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    3.本人要在线上用

    那别忘了做个特别:

    Function.prototype.bind = Function.prototype.bind || function () { …… };

    1
    2
    3
    Function.prototype.bind = Function.prototype.bind || function () {
        ……
    };

    自然最佳是用es5-shim啦。

                if (document.addEventListener) {

    打赏援助自身写出更多好小说,多谢!

    新葡亰496net 1

    1 赞 7 收藏 评论

      this.getName = function(){

    最终代码

    从而最末尾的代码正是:

    Function.prototype.bind2 = function (context) { if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; var args = Array.prototype.slice.call(arguments, 1); 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; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Function.prototype.bind2 = function (context) {
     
        if (typeof this !== "function") {
          throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
        }
     
        var self = this;
        var args = Array.prototype.slice.call(arguments, 1);
        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;
     
    }

                    document.addEventListener('mousemove', ?);   //this.move?  

    关于小编:韩子迟

    新葡亰496net 2

    a JavaScript beginner 个人主页 · 作者的小说 · 9 ·    

    新葡亰496net 3

        setTimeout(function(){

    深刻类别

    JavaScript深远系列目录地址:。

    JavaScript深远种类估计写十五篇左右,意在帮大家捋顺JavaScript底层知识,器重教学如原型、成效域、实行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、承袭等困难概念。

    假定有错误也许不谨慎的地点,请务必给予指正,拾贰分多谢。借使喜欢依然有所启发,招待star,对我也是一种鞭策。

    本系列:

    1. JavaScirpt 深远之从原型到原型链
    2. JavaScript 深切之词法成效域和动态功效域
    3. JavaScript 深远之施行上下文栈
    4. JavaScript 浓密之变量对象
    5. JavaScript 深刻之成效域链
    6. JavaScript 深入之从 ECMAScript 规范解读 this
    7. JavaScript 深远之施行上下文
    8. JavaScript 深远之闭包
    9. JavaScript 深切之参数按值传递
    10. JavaScript 深远之call和apply的效仿完毕

      1 赞 收藏 评论

    新葡亰496net 4

                } else if (document.attachEvent) {

          console.log("Hello,my name is " this.name);

                    document.attach伊芙nt("onmousemove", ?);     //this.move?怎么放进去

        },100);

                }

      }

     

    }

            };

    var weiqi = new Person("卫旗");

            Mouse.prototype.move = function (arg1,arg2,event) {

    weiqi.getName(); 

                event = window.event || event;

    //Hello,my name is pig

                var x = event.pageX || event.offsetX,

          那一年输出this.name是pig,原因是this的针对性是在运转函数时规定的,而不是在概念函数时规定的,再因为setTimeout是在全局境遇下只想,所以this就对准了window。

            y = event.pageY || event.offsetY;

          从前化解这一个题指标形式经常是缓存this,比方:

                this.position = position = [x, y];

    var name = "pig";

                this.log(arg1,arg2);

    function Person(name){

            };

      this.name = name;

            Mouse.prototype.log = function (arg1, arg2) {

      this.getName = function(){

                console.log(arg1 "," arg2);

        //在此间缓存三个this

                console.log(this.position);

        var self = this;

            };

        setTimeout(function(){

            new Mouse();

          //在这里是有缓存this的self

    www.2cto.com

          console.log("Hello,my name is " self.name);

    地点你精通'?'号那里要干嘛了吧?作者想给document的mousemove绑定自个儿的move方法,但是碰到难点了,那样的话,Mouse.prototype.move

        },100);

    里的this就不会指向Mouse的指标,相信我们通常遇上这种难题.大概你早精通了怎么化解,不过有越来越快更简明的章程呢?答案是:

      }

      Function.prototype.bind()这一个玄妙的玩意儿,不过ie6 7 8都不协理,一般当代浏览器都支持了,大家接下去要做的正是模仿他,

    }

     这么好的秘技自然要效仿它,怎么模仿见上边nothing的原创方法

    var weiqi = new Person("卫旗");

        (function () {

    weiqi.getName();

                var proxy = function (fn, target) {

    //Hello,my name is 卫旗

                    var proxy = function () {

          那样就解决了那么些标题,非常便于,因为它使得setTimeout函数中能够访问Person的上下文。

                        if (2 < arguments.length) { //存在被代理的函数有参数的时候

          现在有三个更加好的化解办法,能够利用bind()函数,上边的例证能够被更新为:

                            var privateArgs = Array.prototype.slice.call(arguments, 2);

    var name = "pig";

                          //从第二个起首收取来,[this,绑定的靶子,参数列表]

    function Person(name){

                            return function () {

      this.name = name;

                                var args = Array.prototype.slice.call(arguments);

      this.getName = function(){

            -->这里的arguments与外边的不是同一个,这几个是被代理的函数内部的arguments对象,

        setTimeout(function(){

           比方这里的move函数的  arguments[0]=[object Event]便是以此事件之中的e参数

          console.log("Hello,my name is " this.name);

     

        }.bind(this),100);

                                Array.prototype.unshift.apply(args, privateArgs);

        //注意上边这一行,加多了bind(this)

     

      }

           -->这里在加上传进来的参数,就兑现了,和原生bind一样的参数方式

    }

         //->而且这里是把个体的参数放到前边的诸如a=new Mouse();a.move(1,2);

    var weiqi = new Person("卫旗");

          //假设那个move方法未有参数,意思正是prototype.move=fn(){arguments} ,

    weiqi.getName();

          //而自个儿传进来了参数,参数的arguments.length=3,

    //Hello,my name is 卫旗

           //arguments[0]=1,arguments[1]=2,arguments[2]新葡亰496net,=[object event].

          bind()最简易的用法是创建贰个函数,使得那些函数无论什么调用都持有一致的this值。JavaScript新手常常犯的三个不当就是将贰个主意从二个对象中拿出来,然后再调用,希望方法中的this是原本的对象(比方在回调函数中传来这些办法)。假如不做特殊管理的话,一般会丢掉原本的对象。从原本的函数和原先的目的成立二个绑定函数,则足以极美的缓慢解决这些难题:

     

    //定义全局变量x

                                return fn.apply(target, args);

    var x = "window";

                            }

    //在module内部定义x

                    //这里之所以搞复杂了,是因为,在被代理的函数能够一直访问arguments,举个例子作者不给被代理的函数字传送参数,而直白选取

    var module = {

                     //那样这一个arguments就能含有与原生Function.prototype.bind的arguments同样的目标,

      x:"module",

                     //这里代码深奥,是因为你没驾驭这里原生的bind里面包车型大巴arguments是怎么,知道了,就清楚干什么绑定本人要好的arguments

      getX:function(){

                    //做那样多,首要目标就是令你被代理的函数内部的arguments与function.prototype.bind里的arguments对象涵盖的事物同样

        console.log(this.x);

                        }

      }

                 

    }

                        return function () {

    module.getX();

                            return fn.apply(target, arguments);

    //重临module,因为在module内部调用getX()

                        }

    var getX = module.getX;

                    }

    getX();

                    return proxy.apply(null, arguments);

    //重返window,因为这么些getX()是在大局作用域中调用的

                };

    //绑定getX()并将this值设为module

                /*支撑原生的运用原生的*/

    var boundGetX = getX.bind(module);

                Function.prototype.bind = Function.prototype.bind ||

    boundGetX();

        function (target) {                   //这里的this指代要被代理的函数

    //再次回到module,绑定以往this值始终为module

            if (1 < arguments.length) {

    浏览器协理景况:

                var args = Array.prototype.slice.call(arguments, 1);  //抽出参数列表

    Browser Version support

                args.unshift(this, target);  //那个args最终成为了[this,绑定的目的,参数列表]

    Chrome 7

                return proxy.apply(null, args);

    FireFox(Gecko) 4.0(2)

     

    Internet Explorer 9

        -->估摸大家会跟17楼犯同样的失实,这里之所以那样复杂的操作arguments对象,只是为着能确认保障传进proxy函数中,保障arguments对象不失效

    Opera 11.60

            }

    Safari 5.14

            return proxy(this, target);

          很不幸,Function.prototype.bind在IE8及以下版本中不被接济,所以如若未有一个盘算方案以来,恐怕会在运营时出现难点。bind函数在ECMA-262第五版才被参与。它或然不不可能在有着浏览器上运营。你能够在脚本有的到场如下代码,让不协理的浏览器也能应用bind()成效。

        };

    if (!Function.prototype.bind) {

            })();

    Function.prototype.bind = function (oThis) {

    www.2cto.com

      if (typeof this !== "function") {

    如上代码为何本身要直接return回来代理,因为如此您才具如此调用this.move.bind(this,1,2)()然后这里会立刻推行函数!

      // 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");

     if (document.addEventListener) {

      }

                    document.addEventListener('mousemove', this.move.bind(this,1,2));

      var aArgs = Array.prototype.slice.call(arguments, 1),

                } else if (document.attachEvent) {

        fToBind = this,

                    document.attachEvent("onmousemove", this.move.bind(this,1,2));

        fNOP = function () {},

                }

        fBound = function () {

    www.2cto.com

        return fToBind.apply(this instanceof fNOP && oThis

     是或不是之后凡是遭逢要充裕事件,然后调用的不二秘籍的this又想指向任何对象,那样是或不是非常粗大略呢..

                    ? this

    观望大家对以上代码有一点点难知晓,来个轻易点得

                    : oThis || window,

     var a = function () {

                    aArgs.concat(Array.prototype.slice.call(arguments)));

                console.log(arguments[0]);   //1

        };

                console.log(arguments[1]);   //2

      fNOP.prototype = this.prototype;

                console.log(this.key1);

      fBound.prototype = new fNOP();

                //那样绑定参数的话,我的参数列出来才干和原生的bind同样,就好像此简单,

      return fBound;

            };

    };

            var b = {

    }

                key1: "value1"

    语法

            };

        fun.bind(thisArg[, arg1[, arg2[, …]]])

     

    参数

         a.bind(b, 1, 2)();

          thisArg,当绑定函数被调用时,该参数会作为原函数运维时的this指向,当使用new操作符调用绑定函数时,该参数无效。

    www.2cto.com

          arg1, arg2, …,当绑定函数被调用时,这几个参数加上绑定函数本人的参数会奉公守法顺序作为原函数运转时的参数。

     

    描述

    商议17楼同学的代码错误,笔者想那是多多益善人会犯的失实,代码如下

          bind()函数会创设四个新的函数(三个绑定的函数)有同一的函数体(在ECMAScript 5 标准内置Call属性),当该函数(绑定函数的原函数)被调用时this值绑定到bind()的首先个参数,该参数无法被重写。绑定函数被调用时,bind()也经受预设的参数提须求原函数。二个绑定函数也能应用new操作符成立对象:这种作为就如把原函数当成构造器。提供的this值被忽视,同事调用的参数被提需求模拟函数。

          Function.prototype.bind = function (target) {

                var self = this;

                return function () {

                    return self.apply(target, arguments); //这里的arguments根本传不进去

                }

            }

              var a = function () {

                  console.log(arguments.length);  //这样bind的话,arguments参数失效

                                                 //arguments.length=0.

                  console.log(this.key1);

              };

            var b = {

                        key1: "value1"

              };

                    a.bind(b, [1, 2], 3)();    //从此间能够见到,期望的arguments.length=2

                    //那也是本身干吗苦口婆心的操作arguments参数

            //小编清楚这里大多数人都会感觉对的,不过你错了,17楼的校友你还得在构思下

     

    不带注释的源码,

         (function () {

                var proxy = function (fn, target) {

                    var proxy = function () {

                        if (2 < arguments.length) {

                            var privateArgs = Array.prototype.slice.call(arguments, 2);

                            return function () {

                                var args = Array.prototype.slice.call(arguments);

                                Array.prototype.unshift.apply(args,privateArgs);

                                return fn.apply(target, args);

                            }

                        }

                        return function () {

                            return fn.apply(target, arguments);

                        }

                    }

                    return proxy.apply(null, arguments);

                };

                /*扶助原生的施用原生的*/

                Function.prototype.bind = Function.prototype.bind ||

        function (target) {               

            if (1 < arguments.length) {

                var args = Array.prototype.slice.call(arguments, 1);

                args.unshift(this, target); 

                return proxy.apply(null, args);

            }

            return proxy(this, target);

        };

            })();

    www.2cto.com

     

     

     

     

    要是需求转发本文,请附上链接

     

     

      

    : var Mouse = function () { // Look! no that = this! this.position = [0, 0]; if (document.addEventListener) { document.addEventListener(mousemove, ?); //this.move? }...

    本文由新葡亰496net发布于新葡亰官网,转载请注明出处:新葡亰496net:这段js代码得拯救你多少时间,深入

    关键词: