🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * ## 一 . Function.prototype.call > call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。 >[info]语法: ~~~ fun.call(thisArg, arg1, arg2, ...) 参数: thisArg 在fun函数运行时指定的this值。 PS:需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this值。 1.如果这个函数处于非严格模式下,则指定为 null 和 undefined 的 this 值会自动指向全局对象( 浏览器中就是 window 对象 ); 2.同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。 arg1, arg2, ... 指定的参数列表。 ~~~ >[info] 用法 1:模拟面向对象的继承 ~~~ function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); /* 这一句相当于: 1.把 Product 函数里的this指向当前函数的环境对象; 2.执行Product函数 等价于,给函数增添了一段代码: this.name = name; this.price = price; */ this.category = 'food'; } console.log(new Food('cheese', 5).name); //输出 'cheese' ~~~ >[info]用法 2:为了避免 for循环语句定义的变量,避免因闭包特性而出错 ~~~ var person= [ {sex: 'man', name: 'wdd'}, {sex: 'woman', name: 'girl'}]; for (var i = 0; i < person.length; i++) { (function (i) { this.print = function () { console.log('My index is',i); } }).call(person[i], i); } 这个函数给原数组的每个元素(为对象),添加了一个 print 方法 ~~~ * * * * * ## 二. Function.prototype.apply >注意:该方法与 call 只有一个区别,就是 call() 方法接受的是若干个参数的列表,而 apply() 方法接受的是一个包含多个参数的数组。 >[info] 用法 1:求出一组数中的最大和最小值 ~~~ 用传统的方法: var numbers = [5, 6, 2, 3, 7]; var max = -Infinity, min = +Infinity; for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; if (numbers[i] < min) min = numbers[i]; } 利用 apply 借用 Math 的方法: Math.max/min(arg1,arg2,arg3,...) var max = Math.max.apply(null, numbers); var min = Math.min.apply(null, numbers); ~~~ * * * * * ## 三. Function.prototype.bind >`bind()` 方法创建一个新的函数, 当被调用时,将其 this 关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。 >[danger] PS:这个方法很大一个功能就是绑定执行环境对象,但是和 call & apply 方法的用法还是很不同的。 >[info]语法: ~~~ fun.bind(thisArg, [arg1,arg2,...]) 参数: thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。 当使用new 操作符调用绑定函数时,该参数无效。 arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。 返回值 返回由指定的this值和初始化参数改造的原函数拷贝 ~~~ >[info]用法1(绑定执行环境对象): ~~~ this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); /* 返回 81 用对象调用这个方法,则函数的执行环境对象就是这个调用对象,即 this 指向这个调用对象 */ var retrieveX = module.getX; retrieveX(); /* 返回 9 在这种情况下,this 指向全局作用域 调用这个函数的环境对象是全局作用域 */ var boundGetX = module.getX.bind(module); /* 构造了一个新函数,这个函数里的 this 固定指向 module */ boundGetX(); // 返回 81 ~~~ >[info]用法二:偏函数(Partial Functions) > `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] ~~~ >[info]用法三:快捷调用 >在你想要为一个需要特定的 this 值的函数创建一个捷径(shortcut)的时候,bind() 方法也很好用。 你可以用 Array.prototype.slice 来将一个类似于数组的对象(array-like object)转换成一个真正的数组,就拿它来举例子吧。 你可以创建这样一个捷径: ~~~ var slice = Array.prototype.slice; /* 数组以及字符串类型下的一些内置函数, 都是需要调用它们的执行环境对象的, 那么这里绑定的对象就被用作执行环境对象。 */ slice.apply(arguments); 用 bind() 可以使这个过程变得简单。 在下面这段代码里面, slice 是 Function.prototype的 apply() 方法的绑定函数, 并且将 Array.prototype 的 slice() 方法作为 this 的值。 这意味着我们压根儿用不着上面那个 apply() 调用了。 var unboundSlice = Array.prototype.slice; var slice = Function.prototype.apply.bind(unboundSlice); slice(arguments); ~~~