这段js代码得拯救你多少时间,你可能需要了解的
分类:澳门新萄京最大平台

有关 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,第88中学也支撑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').addEventListener('click', function(){ logger.updateCount();}); //用这种方式让代码越来越精短,当然那只是bind的风流洒脱种情景document.querySelector('button').addEventListener('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); // [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 一样内容的塞尔维亚共和国(Republic of Serbia卡塔 尔(阿拉伯语:قطر‎语版,就不设有这么些论断!

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) {

打赏协助本人写出越来越多好小说,谢谢!

澳门新萄京 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?  

至于小编:韩子迟

澳门新萄京 2

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

澳门新萄京 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 赞 收藏 评论

澳门新萄京 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]=[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));

这段js代码得拯救你多少时间,你可能需要了解的知识点以及使用场景。    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? }...

本文由澳门新萄京发布于澳门新萄京最大平台,转载请注明出处:这段js代码得拯救你多少时间,你可能需要了解的

上一篇:澳门新萄京个超酷特点,4重大立异 下一篇:没有了
猜你喜欢
热门排行
精彩图文