js 函数调用和this 的理解

357 阅读2分钟

本文是自己关于this(函数上下文)的学习笔记(每次看完都会忘,想了想还是记下来)

函数的隐式参数

首先,隐式的函数参数有thisarguments,两者会静默的传递给函数,并且可以像函数体内显示声明的参数一样正常使用。不过有了剩余参数之后,arguments的使用需求已经减少了。

function func() {
     console.log(arguments.length) //3
     console.log(arguments[0])//1
 }
 func(1, 2, 3)

不过要注意的是,arguments对象并不是数组,只是有个名为length的属性,并且通过数组索引的方式获取单个参数的值。

另外在严格模式时,通过索引的方式不能更改传过来的实参。

"use strict" //严格模式
function func(name, age) {
     console.log(arguments.length) //2
     console.log(name) //Tom
     console.log(arguments[0])//Tom
     
     arguments[0] = 'Jerry'
     
     console.log(name) //Tom
     console.log(arguments[0])//Jerry
 }
 func('Tom',2)

this参数:函数上下文

函数调用的几种方式,函数上下文有所不同

  1. 作为一个函数直接被调用
  2. 作为一个方法被调用,也就是关联在对象上,实现面向对象变成
  3. 作为一个构造函数,实例化一个新的对象
  4. 通过函数的apply或者call方法 (另外关于this指向,还有箭头函数和bind()方法)

作为函数被调用, 非严格模式下,this指向全局,严格模式则是undefined

let name = 'Alice'
function func(name) {
   console.log(this.name); //Alice
   console.log(name); //Tom
}
func('Tom');
(function(name){return name})('Tom')

作为对象的方法被调用,this指向对象

let obj = {
  name: 'Alice',
  func: function(PName) {
    console.log(PName);//Tom
    console.log(this.name);//Alice
  }
}
obj.func('Tom')

作为构造函数调用,this指向新构建对象。(构造函数的目标是创建一个新对象,初始化后将其作为返回值)

function Person(name, age) {
    this.name = name
    this.age = age
    this.logMsg = function(){
        console.log(name + ',' + age)
    }
}
let student = new Person('Tom',12)
student.logMsg() //Tom,12

构造函数调用还有一个需要注意的地方: 如果构造函数返回一个对象,则该对象将作为整个表达式的值返回,而传入构造函数的this将被丢弃;但是如果构造函数返回的是非对象类型,则忽略返回值,返回新创建的对象。

通过apply和call调用

let obj = {
  name: 'Alice',
  func: function(PName) {
    console.log(this.name);
    console.log(PName);
  }
}
let obj1 = {
    name: 'Tom'
}

//第一个参数作为函数上下文,第二个参数是参数数组
obj.func('Jerry'); // Alice, Jerry
obj.func.apply(obj1, ['Tina']); //Tom, Tina

箭头函数

箭头函数不会隐式传入this参数,没有单独的this,与声明所在的上下文相同 在全局代码中定义对象字面量,在字面量中定义箭头函数时,箭头函数内的this指向全局对象

let obj = {
    click: ()=> {
    //this指向全局window对象
    }
}

bind()

函数的bind方法创建新函数,并且创建的新函数与原始函数的函数体相同

let obj = {
  name: 'Alice',
  func: function(PName) {
    console.log(this.name);
  }
}
func1={
    name: 'Tom'
}
obj.func.bind(func1)();//Tom