那了解了函数 this 指向的不同场景之后,我们知道有些情况下我们为了使用某种特定环境的 this 引用,这时候时候我们就需要采用一些特殊手段来处理了,例如我们经常在定时器外部备份 this 引用,然后在定时器函数内部使用外部 this 的引用。
然而实际上对于这种做法我们的 JavaScript 为我们专门提供了一些函数方法用来帮我们更优雅的处理函数内部 this 指向问题。
那就是 call、apply、bind 三个函数方法。
call()
方法调用一个函数, 其具有一个指定的 this
值和分别地提供的参数(参数的列表)。
注意:该方法的作用和 apply()
方法类似,只有一个区别,就是 call()
方法接受的是若干个参数的列表,而 apply()
方法接受的是一个包含多个参数的数组。
语法:
fun.call(thisArg[, arg1[, arg2[, ...]]])
参数:
thisArg
arg1, arg2, ...
apply()
方法调用一个函数, 其具有一个指定的 this
值,以及作为一个数组(或类似数组的对象)提供的参数。
注意:该方法的作用和 call()
方法类似,只有一个区别,就是 call()
方法接受的是若干个参数的列表,而 apply()
方法接受的是一个包含多个参数的数组。
语法:
fun.apply(thisArg, [argsArray])
参数:
thisArg
argsArray
apply()
与 call()
非常相似,不同之处在于提供参数的方式。apply()
使用参数数组而不是一组参数列表。例如:
fun.apply(this, ['eat', 'bananas'])
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> <script> //apply和call的使用 //作用:可以改变this的指向 function f1(x,y) { console.log("结果是:"+(x+y)+this); return "10000"; } f1(10,20);//函数的调用 console.log("========"); //此时的f1实际上是当成对象来使用的,对象可以调用方法 //apply和call方法也是函数的调用的方式 f1.apply(); f1.call(); console.log("=========="); f1.apply(null); f1.call(null); //apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是默认的window f1.apply(null,[100,200]); f1.call(null,100,200); //apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的 var result1=f1.apply(null,[10,20]); var result2=f1.call(null,10,20); console.log(result1); console.log(result2); console.log("=============================="); // function f1(x,y) { // console.log("这个函数是window对象的一个方法:"+(x+y)+this.sex); // } // window.f1(10,20); // //obj是一个对象 // var obj={ // age:10, // sex:"男" // }; // // window.f1.apply(obj,[10,20]); // window.f1.call(obj,10,20); // console.dir(obj); //apply和call可以改变this的指向 function Person(age,sex) { this.age=age; this.sex=sex; } //通过原型添加方法 Person.prototype.sayHi=function (x,y) { console.log("您好啊:"+this.sex); return 1000; }; var per=new Person(10,"男"); per.sayHi(); console.log("=============="); function Student(name,sex) { this.name=name; this.sex=sex; } var stu=new Student("小明","女"); var r1=per.sayHi.apply(stu); var r2=per.sayHi.call(stu); console.log(r1); console.log(r2); </script> </head> <body> </body> </html>
bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。
当目标函数被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。
绑定函数被调用时,bind() 也接受预设的参数提供给原函数。
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
语法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
参数:
thisArg
arg1, arg2, …
返回值:
返回由指定的this值和初始化参数改造的原函数拷贝。
示例1:
this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 返回 81 var retrieveX = module.getX; retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域 // 创建一个新函数,将"this"绑定到module对象 // 新手可能会被全局的x变量和module里的属性x所迷惑 var boundGetX = retrieveX.bind(module); boundGetX(); // 返回 81
示例2:
function LateBloomer() { this.petalCount = Math.ceil(Math.random() * 12) + 1; } // Declare bloom after a delay of 1 second LateBloomer.prototype.bloom = function() { window.setTimeout(this.declare.bind(this), 1000); }; LateBloomer.prototype.declare = function() { console.log('I am a beautiful flower with ' + this.petalCount + ' petals!'); }; var flower = new LateBloomer(); flower.bloom(); // 一秒钟后, 调用'declare'方法
call 和 apply 特性一样
this
的指向null
或者 undefined
则内部 this 指向 windowbind