javascript —— this篇

从零开始学习javascript ———— this

本专辑是参考了侯策老师出版的书籍《前端开发核心知识进阶》整理的学习笔记。

关于this指向的问题,我们可以先记住以下几点,后面会依次论证:

  • 在 use strict 模式下this指向undefined,在非严格模式下this指向window
  • 通过callapplybind显式调用函数时,this会被绑定到指定参数对象上。(优先级:bind大于callapply
  • 使用new方法调用构造函数时,会创建一个新的对象,并且会将this绑定到新创建对象上面,同时给这个对象设置属性和方法
  • 关于function(){}:通过上下文对象调用函数时,this会指向到这个对象上面,否则指向全局,并且this可以被显式修改
  • 关于() => {}:箭头函数的this指向是由外层(函数或者全局)作用域决定的,并且this不能被显式修改

全局函数中的this

看一段代码:

function fn1() {
    console.log(this);
}
function fn2() {
    "use strict"
    console.log(this);

}
fn1(); //Window
fn2(); //undefined
复制代码

通过代码我们可以看到,在非严格模式下this指向Window这个全局对象,严格模式下this指向undefined

通过callapplybind修改this指向,以及优先级的问题

基本使用

var target = {
    name: "张三"
}
function fn(arg1, arg2) {
    console.log(this.name);
    console.log(arg1);
    console.log(arg2);
}

//call
fn.call(target, 1, 2) //张三 1  2

//apply
fn.apply(target, [3, 4]) //张三 3  4

//bind
const func = fn.bind(target, 5, 6);
func(); // 张三  5  6
复制代码

优先级的问题

我们通常把apply、call、bind这种修改this的方式,成为显式绑定。那么,它们之间谁的优先级更高呢?

执行代码:

var target1 = {
    name: "张三"
}
var target2 = {
    name: "李四"
}

function fn(arg1, arg2) {
    console.log(this.name);
    console.log(arg1);
    console.log(arg2);
}
const func = fn.bind(target1, 5, 6);
func(); // 输出:张三  5  6

// 通过call显式指定this,还是输出原本的值
func.call(target2)// 输出:张三  5  6
复制代码

通过上面的代码我们可以看到,func是一个通过bind方法构造的函数,并且自动绑定了thistarget1,通过call显式绑定this为target2时,输出值依然不变,所以bind的优先级是最高的。此外还需要注意,如果bind时传入了参数,后续给由bind创建的函数传任何参数都是没用的。

不同点

  1. call和apply参数设定不一样。但是apply有一个特性,接收一个数组参数,但是会将参数逐一传递
  2. bind是创建一个函数,而call、apply是执行一个函数。

new调用构造函数时的this问题

关于构造函数和this的问题,我们先来看一段代码:

function Fn() {
    this.name = "张三";
    this.log = function () {
        console.log("log");
    }
}
const instance = new Fn();
console.log(instance); //输出:{name:"张三",log:function(){}}
复制代码

上面的代码,往往涉及到一个问题:new调用构造函数的时候,做了什么操作?

  • 创建一个新的对象
  • 将构造函数的this指向一个新的对象
  • 为新创建的对象设置属性和方法
  • 返回这个对象

function(){}中的this

我们先来总结一下在function(){}中有哪几种改变this的方式:

  1. 通过call、apply、bind显式绑定this
  2. 通过改变上下文调用对象。(举例:obj.fn() 此时this指向obj)

除过上面俩种情况,this都指向window(非严格模式)。

参考上面我们得出的结论:运行以下代码,最终会返回true

const obj = {
    name: "杨志强",
    fn: function () {
        return this;

    }
}
console.log(obj === obj.fn());
复制代码

还需要我们注意的就是,当存在更复杂的嵌套关系时,this会指向最后调用他的对象:

var target = {
    name: "target",
    child: {
        name: "child",
        fn() {
            console.log(this);
        }
    }
}
target.child.fn();// 输出:{name:"child",fn:function(){}}
复制代码

() => {}中的this

始终记住:箭头函数的this是由外层(函数或全局作用域)决定的,并且this的指向不能被显式绑定,不能实例化

看一个例子:

我们目的是要输出target对象中的count

var target = {
    count: 1,
    fn: function () {
        setInterval(function () {
            console.log(this);
            console.log(this.count);
        }, 1000)

    }
}
target.fn();// 输出:window undefined
复制代码

分析代码:通过上面学的知识,我们可以知道functionthis是由上下文对象决定的,否则就指向window,要想输出count,我们可以通过箭头函数来解决这个问题。

修改代码

var target = {
    count: 1,
    fn: function () {
        setInterval(() => {
            console.log(this);
            console.log(this.count);
        }, 1000)

    }
}
target.fn();// 输出:{count:1,fn:function(){}} 1 
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享