本文是自己关于this(函数上下文)的学习笔记(每次看完都会忘,想了想还是记下来)
函数的隐式参数
首先,隐式的函数参数有this和arguments,两者会静默的传递给函数,并且可以像函数体内显示声明的参数一样正常使用。不过有了剩余参数之后,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参数:函数上下文
函数调用的几种方式,函数上下文有所不同
- 作为一个函数直接被调用
- 作为一个方法被调用,也就是关联在对象上,实现面向对象变成
- 作为一个构造函数,实例化一个新的对象
- 通过函数的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