JavaScript中的this

1,浏览器和node中全局作用域下的this

2.绑定规则

3.默认绑定

4.隐式绑定

5.apply、bind、call的显式绑定及其对应的特殊绑定

6,new绑定

7.特殊绑定(包括箭头函数、间接函数引用(obj1.foo=obj2.foo)()的绑定、内置函数(setTimeout、foreach、div的点击))

8.绑定优先级

9.面试题

1.浏览器和node中全局作用域下的this

浏览器下的this是window,node环境下的this是{},也就是绑定全局对象,在node中全局对象是global,浏览器下的全局对象是window,最新的es里面推出了globalThis,在浏览器里面globalThis和window相等,在nodeglobalThis等于global

2.绑定规则

绑定规则有四种:默认绑定、隐式绑定、显式绑定、new绑定

3.默认绑定

通过以下三个案例,我们可以得知:1.当函数调用的时候,就会给一个this。2,.this和函数的定义位置无关,而是和调用者有关,当没有调用者的时候,指向全局对象,以下代码在node测试,所以指向global

// 默认绑定 三种常见默认
// 1.直接调用
function foo(){
  console.log(this);
}
foo()//global
// 2.函数内间接调用
function foo1(){
  console.log(this);
}
function foo2(){
  foo1()
}
foo2()//global
// 赋值调用
let obj={
  foo:function foo3(){
    console.log(this);
  }
}
let bar=obj.foo
bar() //global
//案例四 函数调用函数内再调用
function foo11(){
function  foo12(){
  console.log(this);
}
foo12()
}
foo11()//global

4.隐式绑定

调用后都指向对象

// 隐式绑定
// 两种情况:对象.函数()和对象.对象.函数()
// 1.对象.函数()
let obj={
  foo:function foo(){
  console.log(this);
  }
}
obj.foo()//{ foo: [Function: foo] }
// 2.对象.对象.函数()
let obj1={
  obj
}
obj1.obj.foo()//{ foo: [Function: foo] }

5.apply、bind、call的显式绑定及其对应的特殊绑定

三种显式绑定的区别,bind是不调用的,其他两种会调用     apply和call的区别在于传参的区别,一个传数组,具体见下

// 显式调用
function foo(x,y){
  console.log(this,x,y);
}
foo.apply({a:1},[1,3])//{ a: 1 } 1 3
foo.call({b:2},2,3)//{ b: 2 } 2 3
// 对于bind的使用 不是foo.bind({c:3})后然后foo()即可 那样指向的是全局对象
let bar=foo.bind({c:3})
bar(4,4)//{ c: 3 } 4 4
foo.apply(null)//global
foo.apply(undefined)//global
foo.call(null)//global
foo.call(undefined)//global
let bar1=foo.bind(null)
bar1(undefined)//global
let bar2=foo.bind(undefined)
bar2(undefined)//global

6.new绑定

// new的绑定
// 当new的时候会执行四件事情
// 1.创建一个新对象
// 2.原型链指向新对象
// 3.this绑定新对象
// 4.返回对象  如果函数没有返回对象 就返回这个函数对象 
function foo(){
  console.log(this);
  return {a:1}
}
let p=new foo()    //foo {} 会打印出这个 代表在new的时候 首先会执行一次
console.log(p);//{ a: 1 }如果里面有函数,函数就绑定到p里面

7.特殊绑定(包括箭头函数、间接函数引用(obj1.foo=obj2.foo)()的绑定、内置函数(setTimeout、foreach、div的点击))

// 特殊绑定规则
// 1.箭头函数不绑定this 会取上层的this
// 2.间接函数的绑定
var obj={
  foo:function(){
    console.log(this);
  }
}
var obj1={};//注意这里的;不要漏了 不然会报错
// 相当于obj1.foo=obj.foo 然后obj1.foo()
(obj1.foo=obj.foo)()//global
// 3.setTimeout的this的绑定
setTimeout(function(){//这里需要function  箭头函数是拿上层对象
  console.log(this);//node:Timeout{}  浏览器:window
  console.log(this===global);//node:false  浏览器:true
})
// 3.对于foreach的this的绑定
let arr=[14]
arr.forEach(function(){
  console.log(this);//global
})
arr.forEach(function(){//箭头函数是拿上层对象
  console.log(this);//{ a: 0 } this指向的是第二个参数
},{a:0})

8.绑定优先级

1.隐式绑定大于默认绑定

2.显式绑定和new绑定大于隐式绑定

3.new绑定大于bind绑定

function foo() {
  console.log(this)
}
var bar = foo.bind("aaa")
var obj = new bar()//foo {}

9.面试题

对于这类题目的分析思路 首先看调用者是谁 然后看是不是箭头函数 如果遇到foo.call(obj) 并且不是箭头函数就相当于obj.foo()

注意对象的{}不算块级作用域

注意apply、call会改变上层作用域

(person.sayName)(); //person 相当于person.sayName()这种调用方式

var name = "window";

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

function sayName() {
  var sss = person.sayName;
  sss(); //window 前面是赋值没有调用 调用的时候没有调用者 默认绑定
  person.sayName(); //person person调用 隐式绑定
  (person.sayName)(); //person 相当于person.sayName()这种调用方式
  (b = person.sayName)(); //window 函数间接调用 
}

sayName();
var name = 'window'

var person1 = {
  name: 'person1',
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person2 = { name: 'person2' }

// person1.foo1(); // person1(隐式绑定)
// person1.foo1.call(person2); // person2(显示绑定优先级大于隐式绑定)

// person1.foo2(); // window(不绑定作用域,上层作用域是全局)
// person1.foo2.call(person2); // window 箭头函数不绑定this, 上层作用域this是window )

// person1.foo3()(); // window(独立函数调用)
// person1.foo3.call(person2)(); // window(独立函数调用)
// person1.foo3().call(person2); // person2(最终调用返回函数式, 使用的是显示绑定)

// person1.foo4()(); // person1(箭头函数不绑定this, 上层作用域this是person1)
// person1.foo4.call(person2)(); // person2(上层作用域被显示的绑定了一个person2)  相当于person2.foo4()()
// person1.foo4().call(person2); // person1(上层找到person1)
var name = 'window'

function Person (name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person1 = new Person('person1')
var person2 = new Person('person2')

person1.foo1() // person1
person1.foo1.call(person2) // person2(显示高于隐式绑定)

person1.foo2() // person1 (上层作用域中的this是person1)
person1.foo2.call(person2) // person1 (上层作用域中的this是person1)

person1.foo3()() // window(独立函数调用)
person1.foo3.call(person2)() // window
person1.foo3().call(person2) // person2

person1.foo4()() // person1
person1.foo4.call(person2)() // person2
person1.foo4().call(person2) // person1


var obj = {
  name: "obj",
  foo: function() {

  }
}


var name = 'window'

function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    foo1: function () {
      return function () {
        console.log(this.name)
      }
    },
    foo2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}

var person1 = new Person('person1')
var person2 = new Person('person2')

person1.obj.foo1()() // window
person1.obj.foo1.call(person2)() // window
person1.obj.foo1().call(person2) // person2

person1.obj.foo2()() // obj
person1.obj.foo2.call(person2)() // person2
person1.obj.foo2().call(person2) // obj


// 

// 上层作用域的理解
// var obj = {
//   name: "obj",
//   foo: function() {
//     // 上层作用域是全局
//   }
// }

// function Student() {
//   this.foo = function() {

//   }
// }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值