Skip to content

JavaScript执行:函数、this #9

@K-Kevin

Description

@K-Kevin

ref:《重学前端》

有多少种函数

第一种,普通函数:用function关键字定义的函数

function foo(){
    // code
}

第二种,箭头函数:用 => 运算符定义的函数

const foo = () => {
    // code
}

第三种,方法:在class中定义的函数

class C {
    foo(){
        //code
    }
}

第四种,生成器函数:用function * 定义的函数

function* foo(){
    // code
}

第五种,类:用class定义的类,实际上也是函数

class Foo {
    constructor(){
        //code
    }
}

第六/七/八种,异步函数:普通函数、箭头函数和生成器函数加上async关键字

async function foo(){
    // code
}
const foo = async () => {
    // code
}
async function foo*(){
    // code
}

this关键字

this是执行上下文中很重要的一个组成部分。同一个函数调用方式不同,得到的this值也不同

function showThis(){
    console.log(this);
}

var o = {
    showThis: showThis
}

showThis(); // global
o.showThis(); // o

调用函数时使用的引用,决定了函数执行时刻的this值

换成箭头函数,结果就不一样了:

const showThis = () => {
    console.log(this);
}

var o = {
    showThis: showThis
}

showThis(); // global
o.showThis(); // global

我们看到,改为箭头函数后,不论用什么引用来调用它,都不影响它的this值

接下来我们看看“方法”,它的行为又不一样了:

class C {
    showThis() {
        console.log(this);
    }
}
var o = new C();
var showThis = o.showThis;

showThis(); // undefined
o.showThis(); // o

这里我们创建了一个类C,并且实例化出对象o,再把o的方法赋值给了变量showThis。

这时候,我们使用showThis这个引用去调用方法时,得到了undefined。

所以,在方法中,我们看到this的行为也不太一样,它得到了undefined的结果

按照我们上面的方法,不难验证出:生成器函数、异步生成器函数和异步普通函数跟普通函数行为是一致的,异步箭头函数与箭头函数行为是一致的。

imp==>

方法的行为跟普通函数有差异,恰恰是因为class设计成了默认按strict模式执行。

我们可以用strict达成与上面方法的例子一样的效果:

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

var o = {
    showThis: showThis
}

showThis(); // undefined
o.showThis(); // o

嵌套的箭头函数中的代码都指向外层this

var o = {}
o.foo = function foo(){
    console.log(this);
    return () => {
        console.log(this);
        return () => console.log(this);
    }
}

o.foo()()(); // o, o, o

操作this的内置函数

Function.prototype.call 和 Function.prototype.apply 可以指定函数调用时传入的this值,示例如下:

function foo(a, b, c){
    console.log(this);
    console.log(a, b, c);
}
foo.call({}, 1, 2, 3);
foo.apply({}, [1, 2, 3]);

这里call和apply作用是一样的,只是传参方式有区别

此外,还有 Function.prototype.bind 它可以生成一个绑定过的函数,这个函数的this值固定了参数:

function foo(a, b, c){
    console.log(this);
    console.log(a, b, c);
}
foo.bind({}, 1, 2, 3)();

call、bind和apply用于不接受this的函数类型如箭头、class都不会报错。

这时候,它们无法实现改变this的能力,但是可以实现传参.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions