要熟悉这三个api,我们首先就要了解this。
this
- 在全局执行环境中,无论是否在严格模式下, this 都指向全局对象。
this.w=2
console.log(w);//2
console.log(this===window);//true
这里this就是指全局对象window
- 在函数环境中,非严格模式下
function f(){
console.log(this)
}
f();//window{...}
在调用f函数时,我们可以理解为window.f(),this指的就是window对象
- 在函数环境中,严格模式下
function f2(){
"use strict"; // 这里是严格模式
console.log(this)
}
f2(); // undefined
这里的this的确应该是undefined,因为f2是被直接调用的,而不是作为对象的属性或方法调用的(如 window.f2())。
4.作为构造器
function Square(width){
this.width=width
}
Square.prototype.getArea=function(){
return this.width*this.width
}
Square.prototype.getLength=function(){
return this.width*4
}
let S=new Square(5)
S.getArea();//25
S.getLength();//20
当this是在new操作符的函数里是时,this就被绑定在这个构造函数的对象(S)上了 5. 直接作为对象
name="Nuna"
let obj={
name:"Cris",
age:18,
fn:function(){
return this.name
}
}
obj.fn();//"Cris"
let globalFn=obj.fn
globalFn();//"Nuna"
在上面这个例子中,this===obj,但是,在只拿到fn的value时,function(){ return this.name }就成了全局函数,这时的this就是window,所以得到的是全局变量name
- 作为一个内联事件处理函数
当代码被内联on-event 处理函数调用时,它的this指向监听器所在的DOM元素
<button onclick="alert(this.tagName.toLowerCase());">
Show this
</button>
点击button窗口会弹出"button"
- 箭头函数没有this/arguments属性
如果要想把 this 的值从一个环境传到另一个,就要用 call 或者apply 方法。
call
call() 方法使用一个指定的 this >值和单独给出的一个或多个参数来调用一个函数。
语法:
function.call(thisArg,arg1,age2,...)
thisArg:在 function 函数运行时使用的 this 值。
arg1, arg2, ...:指定的参数列表。
- 在非严格模式下,this 会指向对应类型的包装对象。
function f(){
console.log(this)
}
f.call() // Window{...}
f.call(null) // Window{...}
f.call(undefined) // Window{...}
f.call(1) // Number{1}
f.call('') // String{""}
f.call(true) // Boolean{true}
f.call({name:"Jane"})//{name: "Jane"}
使用严格模式
function f2() {
'use strict'
console.log(this)
}
f2.call() // undefined
f2.call(undefined) // undefined
f2.call(null) // null
f2.call(1) //1
f2.call('s')//s
f2.call()true//true
f2.call({name:"Jane"})//{name: "Jane"}
- 使用 call 方法调用父构造函数
function Fun1(name, age) {
this.name = name;
this.age = age;
}
function Fun2(name, age) {
Fun1.call(this, name, age);
this.gender = 'man';
}
var result = new Fun2('Cris', 15);
result; // Fun2{name: "Cris", age: 15, gender: "man"}
- 使用 call 方法调用匿名函数
let obj={name:"Jane"};
!function(){
console.log(this.name)
}.call(obj)
匿名函数后面接.call()会立即调用函数
- 使用 call 方法调用函数并且指定上下文的 'this'
function range(){
let arr=[this.min,'~',this.max].join('')
console.log(arr)
}
let obj={min:12,max:20}
range.call(obj) // 12~20
apply
apply()方法的作用和call()方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
- 用 apply 将数组添加到另一个数组
let arr1=[1,2,3]
let arr2=[4,5]
arr1.push.apply(arr1,arr2)
console.log(arr1) //[1,2,3,4,5]
虽然直接用concat()也能将两个数组合并在一个数组,但它并不附加在现有数组上,而push.apply()可直接将被合并数组附加在现有数组上,同时若直接用push()会将被合并数组当做一个整体元素添加到现有数组里。
- 使用apply和内置函数
var numbers = [5, 6, 2, 3, 7];
//应用(apply) Math.min/Math.max 内置函数完成
var max = Math.max.apply(null, numbers);
//基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..)
var min = Math.min.apply(null, numbers);
- 指定this值和参数的函数结果
function f(x,y){
console.log(x,y)
}
f.apply(null,[1,2]) // 1 2
bind
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
let obj={
name:"Cris",
age:2,
f1:function(i){
console.log(this.name+':'+this.age+i)
}
}
let f2=obj.f1.bind({name:"jane",age:3},"岁")
f2(); // jane:3岁
f2指定了this为{name:"jane",age:3},同时还指定了参数i为“岁”
apply、call、bind总结:
apply、call、bind 三者都是用来改变函数this对象的指向。
apply、call、bind 三者第一个参数都是this要指向的对象,也就是指定的上下文。
apply、call、bind 三者都可以利用后续参数传参。
bind是返回对应的函数,便于稍后调用。 apply、call 则是立即调用。