JavaScript 函数的定义、调用、this指向、改变this指向

前端 · 2020-08-13 ·

1 函数的定义方式

  • 自定义函数(命名函数)
  • 函数表达式(匿名函数)
  • 利用 new Function('参数1','参数2'...,'函数体')
//1.1 自定义函数(命名函数)
function fn1() {
    console.log("fn1");
}
fn1();
//1.2 函数表达式(匿名函数)
var fun1 = function(x, y) {
    console.log(x + y)
}
fun1(1, 2);
//1.3 利用 new Function
var obj1 = new Function('x', 'y', 'console.log(x+y)');
obj1(3, 4);
//所有函数都是 Function 的实例对象
console.dir(obj1);

所有函数都是 Function 的实例对象

2 函数的调用方式

  • 普通函数
  • 对象里面的方法
  • 构造函数
  • 绑定时间函数
  • 定时器函数
  • 立即执行函数
//2.1 普通函数
function fn2() {
    console.log("fn2");
}
fn2();
fn2.call();
//2.2 对象里面的方法
var obj2 = {
    fn2: function() {
        console.log("obj2.fn2");
    }
}
obj2.fn2();
//2.3 构造函数
function Object2() {

}
var object2 = new Object2();

//2.4 绑定事件函数 点击了窗口就可以调用这个函数
window.onclick = function() {
        console.log("window.onclick");
}
//2.5 定时器函数  定时器自动1s后调用函数
setTimeout(function() {
    console.log("setTimeout function")
}, 1000);
//2.6 立即执行函数  自动调用
(function() {
    console.log("IFEE");
})();

3 函数内this的指向

this的指向,是当我们调用函数的时候确定的,调用方式的不同决定了this的指向不同一般指向我们的调用者。

调用方式 this指向
普通函数调用 window
构造函数调用 实例对象
对象方法调用 该方法所属对象
事件绑定方法 绑定的事件对象
定时器函数 window
立即执行函数 window
//3.1 普通函数 this指向 window 相当于 window.fn3()
function fn3() {
    console.log("普通函数的this" + this);
}
fn3();
fn3.call();
//3.2 对象里面的方法 this指向的对象obj2
var obj2 = {
    name: "obj2",
    fn3: function() {
        console.log("对象方法的this" + this);
        console.log("对象方法的this的name属性:" + this.name);
    }
}
obj2.fn3();
//3.3 构造函数的this指向object3实例对象
function Object3() {

}
// 原型对象里面的this指向的也是object3 实例对象
Object3.prototype.eat = function() {

}
var object3 = new Object3();

//3.4 绑定事件函数的this指向的是函数调用者 btn 这个按钮对象
var btn = document.querySelector('button');
btn.onclick = function() {
        console.log("事件函数中的this:" + this);
    }
//3.5定时器函数的this指向window
setTimeout(function() {
    console.log("定时器中的this:" + this);
}, 1000);
// 3.6 立即执行函数的this指向window
(function() {
    console.log("立即执行函数的this:" + this);
})();

4 改变函数内this的指向

JavaScript 为我们提供了一些函数方法帮我们改变函数内部this的指向问题,常用的有 bind()、call()、apply()三种方法。

4.1 call方法

call() 方法可以调用一个对象(可理解为调用函数同时可以改变函数的this指向)

// fun.call(thisArg, arg1, arg2, ...)
//4.1 call()
var o4 = {
    name: 'call方法'
}

function fn4(x, y) {
    console.log(this);
    console.log(x + y);
}
fn4.call(window, 3, 3);
fn4.call(o4, 2, 3);
// call 的主要作用可以实现继承
function Father(uname, uage) {
    this.uname = uname;
    this.uag = uage;
}

function Son(uname, uage) {
    Father.call(this, uname, uage);
}
var son = new Son('son1', 20);
console.log(son);

4.2 apply方法

apply()方法调用一个函数。简单理解为调用函数的方式,同时可以改变函数的this指向

// fun.call(thisArg, [argsArray])
// thisArg:在fun函数运行时指定this值
// argsArray:传递的值。必须包含在数组里面
// 返回值就是函数的返回值,因为它就是调用函数
var o42 = {
    name: 'apply方法'
}

function fn4(x, y) {
    console.log(this);
    console.log(x + y);
}
// 1.也是调用函数,同时也可以改变函数内部this指向
// 2.但是他的参数必须是数组(伪数组)
fn4.apply(window, [3, 3]);
fn4.apply(o42, [2, 3]);
// 3.apply 的主要应用 比如我们可以利用 apply 借助于数学内置对象求最大值
var arr = [1, 66, 3, 99, 4];
console.log(Math.max.apply(Math, arr));

4.3 bind方法

bind()方法不会调用函数。但是可以改变函数内部this指向

// fun.bind(thisArg, arg1, arg2, ...)
// thisArg:在fun函数运行时指定this值
// arg1,arg2:传递的其他参数
// 返回由指定的this值和初始化参数改造的原函数拷贝
var o43 = {
    name: 'bind方法'
}

function fn43(x, y) {
    console.log(this);
    console.log(x + y);
}
// 1.方法不会调用函数,但是可以改变this的指向。
// 2.返回的是原函数改变this之后产生的新函数
var fn42new = fn43.bind(o43, 2, 3);
fn42new();
// 3.如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向,此时用bind方法
// 4.我们有一个按钮,当我们点击之后,禁用按钮,3s后开启这个按钮
var btn = document.querySelector('button');
btn.onclick = function() {
    this.disabled = true; // 这个this指向的是btn这个按钮
    var that = this;
    setTimeout(function() {
        that.disabled = false // 定时器函数的this指向的是window
    }, 3000)
}
// 使用bind() 方法
var btn2 = document.querySelector('button');
btn2.onclick = function() {
    this.disabled = true; // 这个this指向的是btn2这个按钮
    setTimeout(function() {
        this.disabled = false // 定时器函数的this指向的是btn2这个对象,因为使用了bind方法
    }.bind(btn2), 3000); // 这里的btn也可以写成this,因为this在setTimeout函数的外面
}

5 call、apply、bind方法

相同点:

都可以改变函数内部的this指向

不同点:

  1. call 和 apply 会调用函数,可以改变this指向
  2. call 和 apply 传递的参数不一样,call 传递参数 arg1,arg2,...形式,apply 必须数组形式[arg]
  3. bind 不会调用函数,可以改变this指向

主要应用场景:

  1. call 经常做继承
  2. apply 经常跟数组有关系,比如借用数学对象实现数组最大值、最小值
  3. bind 不调用函数,但是还想改变this指向的,比如改变定时器函数内部的this指向。
上一篇:
下一篇:
%