深远之bind的模拟完结,javascript中bind函数的功用实例介绍

至于 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,8中不适用,须求伸张通过扩展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() 的其余参数和其原来的参数。

深远之bind的模拟完结,javascript中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伊芙(Eve)ntListener(‘click’,
logger.updateCount.bind(logger));
 

参数

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));
    }
 
}

配合 setTimeout

曾几何时便于丢失 this 指向?恩,set提姆(Tim)eout 是一个意况,很简单把 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长远之从原型到原型链》。

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

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啦。

打赏援助自己写出越来越多好小说,谢谢!

亚洲必赢官网 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;
 
}

有关小编:韩子迟

亚洲必赢官网 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

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

    },100);

  }

}

var weiqi = new Person(“卫旗”);

weiqi.getName(); 

//Hello,my name is pig

     
这么些时候输出this.name是pig,原因是this的针对是在运转函数时规定的,而不是在概念函数时规定的,再因为set提姆(Tim)eout是在全局环境下只想,所以this就针对了window。

      在此之前解决那一个题材的点子平常是缓存this,例如:

var name = “pig”;

function Person(name){

  this.name = name;

  this.getName = function(){

    //在此地缓存一个this

    var self = this;

    setTimeout(function(){

      //在此处是有缓存this的self

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

    },100);

  }

}

var weiqi = new Person(“卫旗”);

weiqi.getName();

//Hello,my name is 卫旗

     
那样就一蹴即至了那个题目,相当有益,因为它使得set提姆eout函数中得以访问Person的上下文。

     
现在有一个更好的解决办法,可以利用bind()函数,上边的例子可以被更新为:

var name = “pig”;

function Person(name){

  this.name = name;

  this.getName = function(){

    setTimeout(function(){

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

    }.bind(this),100);

    //注意上面这一行,添加了bind(this)

  }

}

var weiqi = new Person(“卫旗”);

weiqi.getName();

//Hello,my name is 卫旗

     
bind()最简易的用法是创制一个函数,使得这几个函数无论怎么调用都兼备一致的this值。JavaScript新手平时犯的一个不当就是将一个办法从一个目标中拿出来,然后再调用,希望方法中的this是原来的对象(比如在回调函数中传唱那个办法)。即使不做更加处理的话,一般会丢掉原来的靶子。从原先的函数和原来的对象创立一个绑定函数,则足以很赏心悦目的化解这么些题目:

//定义全局变量x

var x = “window”;

//在module内部定义x

var module = {

  x:”module”,

  getX:function(){

    console.log(this.x);

  }

}

module.getX();

//再次回到module,因为在module内部调用getX()

var getX = module.getX;

getX();

//重临window,因为那些getX()是在大局功用域中调用的

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

var boundGetX = getX.bind(module);

boundGetX();

//重回module,绑定未来this值始终为module

浏览器匡助意况:

Browser Version support

Chrome 7

FireFox(Gecko) 4.0(2)

Internet Explorer 9

Opera 11.60

Safari 5.14

     
很失落,Function.prototype.bind在IE8及以下版本中不被接济,所以假设没有一个准备方案以来,可能会在运行时出现问题。bind函数在ECMA-262第五版才被投入。它恐怕不不能在有着浏览器上运行。你可以在脚本有的参与如下代码,让不协助的浏览器也能使用bind()作用。

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,

    fNOP = function () {},

    fBound = function () {

    return fToBind.apply(this instanceof fNOP && oThis

                ? this

                : oThis || window,

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

    };

  fNOP.prototype = this.prototype;

  fBound.prototype = new fNOP();

  return fBound;

};

}

语法

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

参数

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

      arg1, arg2,
…,当绑定函数被调用时,那几个参数加上绑定函数本身的参数会根据顺序作为原函数运行时的参数。

描述

     
bind()函数会创造一个新的函数(一个绑定的函数)有雷同的函数体(在ECMAScript
5
规范内置Call属性),当该函数(绑定函数的原函数)被调用时this值绑定到bind()的第二个参数,该参数不可以被重写。绑定函数被调用时,bind()也接受预设的参数提须求原函数。一个绑定函数也能利用new操作符创设对象:那种表现就如把原函数当成构造器。提供的this值被忽略,同事调用的参数被提需求模拟函数。

网站地图xml地图