js中this指向详细总结
关于js中this的指向的总结
1.概述
首先要知道,函数中this的指向在函数定义时是决定不了的,只有在函数执行时才能决定指向谁,实际上this始终指向调用这个函数的对象。
2.函数中this指向的三种情况
(1)当函数中有this,但是函数没有被上一级对象调用时
当函数没有被对象调用的时候,函数中的this指向的是默认对象window(注意:严格模式中默认对象不是Window而是undefined)
就相当于是被window调用的。所以此时函数中的this指向的就是window。
function f() {
let a = "hello";
console.log(this.a);//undefined
console.log(this);//window
}
f();
(2)当函数中有this,并且被上一级对象调用时
当函数被上一级对象调用时,此时函数中的this指向的就是调用该函数的对象。
let one = {
a: "hello",
fn: function() {
console.log(this.a);//hello
}
}
one.fn();
(3)当函数中有this,且函数中包含多个对象时
此时尽管这个函数是被最外层对象调用的,但是this依旧只是指向函数的上一级对象
let one = {
a: "hello",
b: {
a: "world",
fn: function() {
console.log(this.a); //world
console.log(this); //{a: "world", fn: ƒ}
}
}
}
one.b.fn();
(4)有个特殊的例子需要注意以下
let one = {
a: "hello",
b: {
a: "world",
fn: function() {
console.log(this.a); //undefined
console.log(this); //Window
}
}
}
let j = one.b.fn;
j();
这里可能会比较迷惑,为什么这里的this又指向了window呢?其实道理也很简单,因为这里只是把one.b.fn的值赋值给了j,并没有调用函数。下面执行到 j() 才调用了函数,而此时没有任何对象调用 j 。现在我们回忆一下之前说的第一种情况,不难想到此时的this指向的应该是window。
3.new 会改变this的指向
function f() {
this.a = "hello";
console.log(this); //f {a: "hello"}
}
let b = new f();
console.log(b.a); //hello
为什么b可以点出f里的a呢,这是因为new关键字可以改变函数中this的指向,将函数的this指向修改为函数的实例化对象。
4.当函数内有this,且该函数有return时
(1)返回值为引用类型的this指向
function f() {
this.a = "hello";
return a{};
}
let b = new f();
console.log(b.a); //undefined
这里为什么又发生了变化?因为当函数返回值为引用类型时,函数中的this会指向它返回的那个对象,也就是这里的{}。那么如果返回值是基本类型会怎么样呢?
(2)返回值为基本类型的this指向
function f() {
this.a = "hello";
return 1;
}
let b = new f();
console.log(b.a); //hello
function f() {
this.a = "hello";
return "world";
}
let b = new f();
console.log(b.a); //hello
可以看到,当返回值是基本类型时,结果和原来是一样的,因此当函数返回值时一个基本类型时,函数中的this指向的时函数的实例化对象。
特例:
function f() {
this.a = "hello";
return null;
}
let b = new f();
console.log(b.a); //hello
虽然null是对象,但是他的结果和基本类型的是一致的。
5.call、apply、bind可以改变函数内this指向
(1)call(this指向的对象,传递参数,参数....)
call可以将函数内的this指向传入的第一个参数,并且call会直接调用该函数,所以call多用于对象的继承。
let o = {
name: 'ldh'
}
function fn(age) {
this.age = age;
console.log(this);
}
fn(18); //window
fn.call(o, 18); //o
console.log(o.age); //18
(2)apply(this指向的对象,数组)
apply和call很相似,都可以改变函数内this的指向并且都会直接调用该函数(调用apply的函数fn:fn.apply(o,[1,2,3])),不同的地方就在于apply必须要用数组传递参数但call不需要,所以apply经常用于跟数组有关系的操作. 比如借助于数学对象实现数组最大值最小值。
let o = {
name: 'ldh'
}
function fn(a, b) {
console.log(this);
console.log(a + b);
}
fn(1, 2); //window 3
fn.apply(o, [1, 2]); //o 3
//借助于数学对象实现数组最大值
let m = Math.max.apply(Math, [1, 56, 12, 74]);
console.log(m);//74
(3)bind(绑定的对象,参数,参数...)
bind也可以改变函数内this指向,但是与call、apply不同的是bind不会直接调用函数,因此想不调用函数,但是还能改变this指向就应该用bind, 比如改变定时器内部的this指向.
let o = {
name: 'ldh'
}
function fn(a, b) {
console.log(this);
console.log(a + b);
}
let f = fn.bind(o, 1, 2);
f();//o 3
浙公网安备 33010602011771号