函数的定义方式

  1. 自定义函数(命名函数)

    function fun() {}
  2. 函数表达式(匿名函数)

    let fun = function() {};
  3. 使用new Function('arg1', 'arg2', ... , '函数体')

    let fun = new Function('x', 'y', 'console.log(x + y)');	// 参数都是字符串形式
    fun(1, 2) 	// 输出 3

所有函数都是Function的实例(对象),函数也是对象,也有原型

fun instanceof Object;	// true
fun.__proto__.constructor === Function; // true

函数的调用与this指向

  1. 普通函数

    function fun() {
        console.log(this);	// this指向window
    }
    fun();	// == window.fun()
  2. 对象的方法

    let wuzi = {
        say: function() {
            console.log(this);	// this指向对象
        }
    }
    wuzi.say();
  3. 构造函数

    // 构造函数以及构造函数的原型对象中的this指向实例对象
    function People() {};
    let wuzi = new People();
  4. 绑定事件函数

    btn.onclick = function() {
        console.log(this);	// 指向函数的调用者,即btn
    };	// 点击触发
  5. 定时器函数

    setInterval(function() {
        console.log(this);	// 指向window
    }, 1000); 	// 每隔一段时间调用一次
  6. 立即执行函数

    // 自动调用
    (function() {
        console.log(this);	// 指向window
    })();

    改变函数内部的this指向

    call

    let wuzi {
        name: 'uzi'
    }
    function fun(a,b) {
        console.log(this);	// wuzi
        console.log(a + b);	// 3
    };
    fun.call(wuzi, 1, 2);	// call调用函数,第一个参数改变函数内部this的指向,后面为函数的参数

    可以使用call实现继承功能

    function Father(name, age) {
        // this 指向父构造函数的对象实例
        this.name = name;
        this.age = age;
    }
    function Son(name, age, sex) {
        // this 指向子构造函数的对象实例
        Father.call(this, name, age);
        this.sex = sex;
    }

    apply

    let wuzi {
        name: 'uzi'
    }
    function fun(a,b) {
        console.log(this);	// wuzi
        console.log(a + b);	// 3
    };
    fun.apply(wuzi, [1, 2]);	// apply调用函数,第一个参数改变函数内部this的指向,参数必须以数组的形式传递

    应用

    let arr = [1, 2, 5, 3, 4];
    let max = Math.max.apply(null, arr);	// 利用数学内置对象求最大值
    // == Math.max.apply(Math, arr);
    // == let max = Max.max(...arr);	// 使用解构

    bind

    let wuzi {
        name: 'uzi'
    }
    function fun(a,b) {
        console.log(this);	// wuzi
        console.log(a + b);	// 3
    };
    let newFun = fun.bind(wuzi, 1, 2); 	// 不会调用函数,返回改造完this后产生的新函数的拷贝
    newFun(); 	// 调用

    如果有的函数不需要立即调用,想要改变函数内部this指向,则应该使用bind

    // 点击按钮后禁用按钮,3秒后恢复
    let btn = document.querySelector('button');
    btn.onclick = function() {
        this.disabled = true;	// this指向btn
        setTimeout(function(){
            this.disabled = false;	// 绑定了btn, 否则this指向window
        }.bind(this), 3000)
    }

    相同点与区别

    相同点:都可以改变函数内部的指向

    区别:

    • call和apply会立即调用函数,bind不会调用
    • call和bind传递参数以逗号分隔,apply必须以将参数放在一个数组中

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

ECharts图表resize 上一篇
构造函数与原型 下一篇