js之this

为什么要用this

function identify() {
    return this.name
}
let people={
    name:'名字'
}
identify.call(people)//返回 '名字'
function identify(context) {
    return context.name
}
let people={
    name:'名字'
}
identify(people)//返回 '名字'
上面的两段代码执行结果是一样的,但是一个用的this,一个是显式的传入context,
当我们设计API时,或者代码复杂后,显示传入context会让代码混乱起来,

this是什么

this是一个运行时的概念,当一个函数被调用,就会创建一个执行上下文,执行上下文里的 lexical environment:词法环境 里就绑定了this指向(之前的执行上下文博客里也说过),指向什么完全取决于函数在哪里被调用(当前的调用栈

this绑定规则

  • 默认绑定
  • 隐式绑定
  • 显示绑定
  • new绑定

默认绑定

//默认绑定
function foo() {
    console.log(this.a)
}
let a=1
foo()//1
//如此foo()直接使用不带修饰的函数引用进行调用的就会进行默认绑定

但是要注意在严格模式下上面的this会指向undefined

隐式绑定

//隐式调用

function foo() {
    console.log(this.a)
}
let obj2={
    a:1,
    foo:foo
}
let obj1={
    a:2,
    obj2:obj2
}
obj.obj2.foo()//1
//当函数拥有调用者,this就会被指向调用者这个对象

这里要着重说下调用者 下面代码就不会隐式绑定this,因为没有实际调用者,就会进行默认绑定

function foo() {
    console.log(this.a)
}

function active(fn) {
    //fn其实foo的引用,参数传递其实是隐式赋值
    fn(); // 真实调用者,为独立调用
}

var a = 20;
var obj = {
    a: 10,
    getA: foo
}

active(obj.getA);
//

显式绑定 (使用call apply bind 绑定this)

function fn(num1, num2) {
    console.log(this.a + num1 + num2);
}
var obj = {
    a: 20
}

fn.call(obj, 100, 10); // 130
fn.apply(obj, [20, 10]); // 50
fn.bind(obj)

call 和apply 都将函数的this指向第一个参数

call和apply实现结果都是一样的,区别在于后面的参数,都是向将要执行的函数传递参数。其中call以一个一个的形式传递,apply以数组的形式传递。这是他们唯一的不同。

我们可以这样使用:

function turnToArray() {
    var arrArgs = [].slice.call(arguments) // 将参数转换成数组
    //arrArgs=Array.from(arguments)
    console.log(arrArgs) // ['a','b']
}
turnToArray('a', 'b')

new绑定

function Person(name, age) {

    // 这里的this指向了谁?
    this.name = name;
    this.age = age;   
}

Person.prototype.getName = function() {

    // 这里的this又指向了谁?
    return this.name;
}

// 上面的2个this,是同一个吗,他们是否指向了原型对象?

var p1 = new Person('Nick', 20);
p1.getName();
//其实都是指向p1这个实例

通过new操作符调用构造函数,会经历以下4个阶段。

  • 创建一个新的对象;
  • 将构造函数的this指向这个新对象;
  • 指向构造函数的代码,为这个对象添加属性,方法等;
  • 返回新对象。

以上绑定方式的优先级 new>显式绑定>隐式绑定>默认绑定

参考 https://yangbo5207.github.io/wutongluo/ji-chu-jin-jie-xi-lie/wu-3001-this.html ;你不知道的js上卷

发表评论

您的电子邮箱地址不会被公开。