JS函数的this指向

发布于:2022-12-17 ⋅ 阅读:(195) ⋅ 点赞:(0)

1. this在全局作用域的指向

在全局作用域下

​ 浏览器:window(globalObject)

​ Node环境下:{}(因为node源码在实现this绑定时 通过call({})绑定的是空对象)

2. this的绑定指向规则

this的绑定和定义的位置没有关系

this的绑定和调用方式以及调用的位置有关

this是在运行时被绑定的

this的绑定规则

① 默认绑定

独立的函数调用可以理解为没有被绑定到某个对象上进行调用--默认绑定

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

foo()  //window

function foo1() {
  console.log(this)  //window
}

function foo2() {
  console.log(this)  //window
	foo1()
}

function foo3() {
  console.log(this)  //window
  foo2()
}

function foo() {
	function bar() {
  	console.log(this)
	}
	return bar
}

var fn = foo()
fn()  //window

var obj = {
  name: "why",
  eating: fn
}

obj.eating() //window 获取到函数后独立调用 指向window

只要函数最后时独立调用 输出都是window

② 隐式绑定

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

var obj = {
  name: "gaofeng"
  foo: foo
}

obj.foo()  // 输出obj对象

隐式绑定的前提是进行调用时,调用的对象内部有对一个函数的引用

③ 显示绑定

call() apply() bind()(bind回返回一个新函数,apply传入的参数以数组方式传递,call直接逗号传递)

unction foo() {
  console.log("函数被调用了", this)
}

// 1.foo直接调用和call/apply调用的不同在于this绑定的不同
foo直接调用指向的是全局对象(window)
foo()

var obj = {
  name: "obj"
}

call/apply是可以指定this的绑定对象
foo.call(obj)
foo.apply(obj)
foo.apply("aaaa")


// 2.call和apply有什么区别?
function sum(num1, num2, num3) {
  console.log(num1 + num2 + num3, this)
}

sum.call("call", 20, 30, 40)
sum.apply("apply", [20, 30, 40])

// 3.call和apply在执行函数时,是可以明确的绑定this, 这个绑定规则称之为显示绑定

④ new绑定

执行操作:

①创建一个全新的对象;

②这个新对象会被执行prototype连接;

③这个新对象会被绑定到函数调用的this上;

④如果函数没有返回其他对象,表达式会返回这个新对象;

通过一个new关键字调用一个函数时(构造器),这个时候this是在调用这个构造器时创建出来的对象

this = 创建出来的对象

这个绑定过程就是new绑定

function Person(name, age) {
  this.name = name
  this.age = age
}

var p = new Person("gaofeng", 18)
console.log(p.name, p.age)   //gaofeng  18

3. this的指向问题其他补充

3.1 一些函数的this分析

①setTimeout(内部实现是将传入的函数独立调用,所以this指向全局,即window,若传入箭头函数,则是根据上层作用域绑定)

②dom的监听事件(绑定的是监听的对象)

③内置API数组.forEach/map/filter/find,默认绑定window,可以传入第二个参数,即绑定this指向

var names = ["abc", "cba", "nba"]

names.forEach(function(item) {
	console.log(item, this)   //window
})

names.forEach(function(item) {
	console.log(item, this)   //abc  "abc"
}, "abc")
names.map(function(item) {
	console.log(item, this)   //abc  "cba"
}, "cba")

4. 绑定规则的优先级

  1. 默认绑定优先级最低

  2. 显示绑定 > 隐式绑定 > 默认绑定

  3. new绑定 > 隐式绑定

 5. 特殊绑定-忽略显示绑定

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

foo.apply("abc")  //abc
foo.apply({})  //{}

// 传入null/underfined 自动绑定成全局对象
foo.apply(null)  // window
foo.apply(underfined)  // window

间接函数引用

var obj1 = {
  name: "obj1",
  foo: function() {
    log(this)
  }
}

var obj2 = {
  name: "obj2"
};

(obj2.bar = obj1.foo)()  // 属于独立调用 window

6. ES6的箭头函数指向

箭头函数不使用this的四种标准规则(也就是不绑定this), 而是根据外层作用域来决定this

对象没有作用域,this指向的是全局,函数有函数的作用域

7. this相关面试题

var name = "window"

var person = {
  name: "person",
  sayName: function () {
    console.log(this.name);
  }
};

function sayName() {
  var sss = person.asyName;
  sss();  // 函数独立调用  this->window  输出"window"
  person.sayName();  // 隐式调用  输出 "person"
  (person.sayName)(); // person: 隐式调用 "person"
  (b = person.sayName)();  //间接函数引用(独立函数调用) 输出window:赋值表达式
}

sayName();
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到