洽谈javascript里的bind

洽谈javascript里的bind,第1张

直击Javascript的严格模式(“use strict”)_WEB前端开发

除了正常运行模式,ECMAscript 5添加了第二种运行模式:“严格模式”(strict mode)。


顾名思义,这种模式使得Javascript在更严格的条件下运行,本文将对”严格模式”做详细介绍。


洽谈javascript里的bind,第2张 理解 javascript 里的 bind() 函数

分享:

bind() 方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给 bind() 的第一个参数, 它的参数是bind()的其他参数和其原本的参数。


语法是这样样子的:

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

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


当使用 new *** 作符调用绑定函数时,该参数无效。


arg1, arg2, … (可选)当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。


参数

bind的第一个参数会作为原函数运行时的this指向,不多说;而第二个开始的参数是可选的,当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。


怎么理解?

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

这有啥用呢?如果某些函数,前几个参数已经 “内定” 了,我们便可以用 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]

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}

一般我们不会去这么用,但是如果要写个 bind 的 polyfill( http://caniuse.com/#search=bind ),还是需要考虑用 new 调用的情况。


我们也可以设置默认值(参考上一小节),原先提供的那些参数仍然会被前置到构造函数调用的前面。


如何居中一个浮动元素?如何让绝对定位的div居中?_WEB前端开发

css快速入门:文中为大家介绍了居中一个浮动元素及让绝对定位的div居中的方法,具有一定的参考价值,希望可以帮助到大家。


浮动元素的上下左右居中:{norder:1px solid red}。


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}

配合 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);

用 canvas 写特效或者做游戏时经常会碰到类似的问题。


上面的代码是有问题的,render 方法中的 this 其实被指向了 window!我们可以用 bind, 显式地把 this 绑定到回调函数以便继续使用该对象。


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

类似的情况还有 dom 的事件监听,一不小心可能 this 就被指向了 dom 元素。


可以参考下以前做 bigrender 时写的这部分代码 https://github.com/hanzichi/hanzichi.github.io/blob/master/2016/bigrender/js/bigrender.js#L179-L184 。


tip

bind还能做一些有意思的事情。


通常来说,将一个类数组转为数组,我们会用 slice(ie9- 不支持)。


参考#14

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

再举个类似的例子,比如说我们要添加事件到多个节点,for 循环当然没有任何问题,我们还可以 “剽窃” forEach 方法:

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

同样类似的,我们可以将 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-5,看起来是道考察闭包的经典题目。


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

也可以用 bind,瞬间逼格提升:

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

推荐教程:《js基础教程》

以上就是洽谈javascript里的bind()函数的详细内容,更多请关注ki4网其它相关文章!

在ps中噪点怎么处理?_WEB前端开发

处理方法:1、用PS打开需要处理的图片,点击菜单栏中的“图像”,再点击图像大小;2、在图像大小中的d窗中重新输入图像的尺寸,将图像宽和高变大,点击“重新采样”选择保留细节(扩大);3、将图片再缩放至原来的大小,此时噪点就已经减少了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/559964.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2020-06-15
下一篇 2020-06-15

发表评论

登录后才能评论

评论列表(0条)

保存