38道关于this的面试题,让你彻底解决this 的指向问题

答案

obj 是通过 var 定义的, obj 会挂载到 window 之上的, obj.foo() 就相当于 window.obj.foo() ,这也印证了 this永远指向最后调用它的那个对象 规则。

题目2.2:对象链式调用

感觉上面总是空谈链式调用的情况,下面直接来看一个例题:

var obj1 = {

a: 1,

obj2: {

a: 2,

foo(){

console.log(this.a)

}

}

}

obj1.obj2.foo() // 2

3.隐式绑定的丢失


隐式绑定可是个调皮的东西,一不小心它就会发生绑定的丢失。一般会有两种常见的丢失:

  • 使用另一个变量作为函数别名,之后使用别名执行函数

  • 将函数作为参数传递时会被隐式赋值

隐式绑定丢失之后, this 的指向会启用默认绑定。

具体来看题目:

题目3.1:取函数别名

a = 1

var obj = {

a: 2,

foo() {

console.log(this.a)

}

}

var foo = obj.foo;

obj.foo();

foo();

JavaScript 对于引用类型,其地址指针存放在栈内存中,真正的本体是存放在堆内存中的。

上面将 obj.foo 赋值给 foo ,就是将 foo 也指向了 obj.foo 所指向的堆内存,此后再执行 foo ,相当于直接执行的堆内存的函数,与 obj 无关, foo 为默认绑定。笼统的记, 只要fn前面什么都没有,肯定不是隐式绑定 。

答案

不要把这里理解成 window.foo 执行,如果 foo 为 let/const 定义, foo 不会挂载到 window 上,但不会影响最后的打印结果

题目3.2:取函数别名

如果取函数别名没有发生在全局,而是发生在对象之中,又会是怎样的结果呢?

var obj = {

a: 1,

foo() {

console.log(this.a)

}

};

var a = 2;

var foo = obj.foo;

var obj2 = { a: 3, foo: obj.foo }

obj.foo();

foo();

obj2.foo();

obj2.foo 指向了 obj.foo 的堆内存,此后执行与 obj 无关(除非使用 call/apply 改变 this 指向)

答案

题目3.3:函数作为参数传递

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

doFoo(obj.foo)

用函数预编译的知识来解答这个问题:函数预编译四部曲前两步分别是:

  1. 找形参和变量声明,值赋予 undefined

  2. 将形参与实参相统一,也就是将实参的值赋予形参。

obj.foo 作为实参,在预编译时将其值赋值给形参 fn ,是将 obj.foo 指向的地址赋给了 fn ,此后 fn 执行不会与 obj 产生任何关系。 fn 为默认绑定。

答案

Window {…}

2

题目3.4:函数作为参数传递

将上面的题略作修改, doFoo 不在 window 上执行,改为在 obj2 中执行

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

var obj2 = { a: 3, doFoo }

obj2.doFoo(obj.foo)

console.log(this)

obj2.doFoo

xxx.fn

doFoo

this

obj2

{a: 3, doFoo: ƒ}

  • fn() : 没有于 obj2 产生联系,默认绑定,打印2

答案

{a: 3, doFoo: ƒ}

2

题目3.5:回调函数

下面这个题目我们写代码时会经常遇到:

var name=‘zcxiaobao’;

function introduce(){

console.log('Hello,My name is ', this.name);

}

const Tom = {

name: ‘TOM’,

introduce: function(){

setTimeout(function(){

console.log(this)

console.log('Hello, My name is ',this.name);

})

}

}

const Mary = {

name: ‘Mary’,

introduce

}

const Lisa = {

name: ‘Lisa’,

introduce

}

Tom.introduce();

setTimeout(Mary.introduce, 100);

setTimeout(function(){

Lisa.introduce();

},200);

setTimeout 是异步调用的,只有当满足条件并且同步代码执行完毕后,才会执行它的回调函数。

Tom.introduce()执行

console

setTimeout

this

window

Mary.introduce

setTimeout

题目3.3

this

Lisa.introduce

setTimeout

xxx.fn

this

答案

Window {…}

Hello, My name is zcxiaobao

Hello,My name is zcxiaobao

Hello,My name is Lisa

所以如果我们想在 setTimeout 或 setInterval 中使用外界的 this ,需要提前存储一下,避免 this 的丢失。

const Tom = {

name: ‘TOM’,

introduce: function(){

_self = this

setTimeout(function(){

console.log('Hello, My name is ',_self.name);

})

}

}

Tom.introduce()

题目3.6:隐式绑定丢失综合题

name = ‘javascript’ ;

let obj = {

name: ‘obj’,

A (){

this.name += ‘this’;

console.log(this.name)

},

B(f){

this.name += ‘this’;

f();

},

C(){

setTimeout(function(){

console.log(this.name);

},1000);

}

}

let a = obj.A;

a();

obj.B(function(){

console.log(this.name);

});

obj.C();

console.log(name);

本题目不做解析,具体可以参照上面的题目。

答案

javascriptthis

javascriptthis

javascriptthis

undefined

4.显式绑定


显式绑定比较好理解,就是通过 call()、apply()、bind() 等方法,强行改变 this 指向。

上面的方法虽然都可以改变 this 指向,但使用起来略有差别:

  • call()和apply() 函数会立即执行

  • bind() 函数会返回新函数,不会立即执行函数

call()和apply()

call

apply

题目4.1:比较三种调用方式

function foo () {

console.log(this.a)

}

var obj = { a: 1 }

var a = 2

foo()

foo.call(obj)

foo.apply(obj)

foo.bind(obj)

  • foo() : 默认绑定。

foo.call(obj)

foo

this

obj

  • foo.apply(obj) : 显式绑定

  • foo.bind(obj) : 显式绑定,但不会立即执行函数,没有返回值

答案

题目4.2:隐式绑定丢失

题目3.4 发生隐式绑定的丢失,如下代码:我们可不可以通过显式绑定来修正这个问题。

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

doFoo(obj.foo)

  1. 首先先修正 doFoo() 函数的 this 指向。

doFoo.call(obj, obj.foo)

  1. 然后修正 fn 的 this 。

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn.call(this)

}

var obj = { a: 1, foo }

var a = 2

doFoo(obj.foo)

大功告成。

题目4.3:回调函数与call

接着上一个题目的风格,稍微变点花样:

var obj1 = {

a: 1

}

var obj2 = {

a: 2,

bar: function () {

console.log(this.a)

},

foo: function () {

setTimeout(function () {

console.log(this)

console.log(this.a)

}.call(obj1), 0)

}

}

var a = 3

obj2.bar()

obj2.foo()

乍一看上去,这个题看起来有些莫名其妙, setTimeout 那是传了个什么东西?

做题之前,先了解一下 setTimeout 的内部机制:(关于异步的执行顺序,可以参考 JavaScript之EventLoop [6] )

setTimeout(fn) {

if (回调条件满足) (

fn

)

}

这样一看,本题就清楚多了,类似 题目4.2 ,修正了回调函数内 fn 的 this 指向。

答案

2

{a: 1}

1

题目4.4:注意call位置

function foo () {

console.log(this.a)

}

var obj = { a: 1 }

var a = 2

foo()

foo.call(obj)

foo().call(obj)

  • foo() : 默认绑定

  • foo.call(obj) : 显式绑定

foo().call(obj)

foo()

call

foo

undefined

call()

答案

2

1

2

Uncaught TypeError: Cannot read property ‘call’ of undefined

题目4.5:注意call位置(2)

上面由于 foo 没有返回函数,无法执行 call 函数报错,因此修改一下 foo 函数,让它返回一个函数。

function foo () {

console.log(this.a)

return function() {

console.log(this.a)

}

}

var obj = { a: 1 }

var a = 2

foo()

foo.call(obj)

foo().call(obj)

  • foo() : 默认绑定

  • foo.call(obj) : 显式绑定

foo().call(obj)

foo()

2

call

this

obj

1

这里千万注意:最后一个 foo().call(obj) 有两个函数执行,会打印 2个值 。

答案

题目4.6:bind

将上面的 call 全部换做 bind 函数,又会怎样那?

call是会立即执行函数,bind会返回一个新函数,但不会执行函数

function foo () {

console.log(this.a)

return function() {

console.log(this.a)

}

}

var obj = { a: 1 }

var a = 2

foo()

foo.bind(obj)

foo().bind(obj)

首先我们要先确定,最后会输出几个值? bind 不会执行函数,因此只有两个 foo() 会打印 a 。

  • foo() : 默认绑定,打印 2

  • foo.bind(obj) : 返回新函数,不会执行函数,无输出

foo().bind(obj)

foo()

2

bind

foo()

this

obj

答案

题目4.7:外层this与内层this

做到这里,不由产生了一些疑问:如果使用 call、bind 等修改了外层函数的 this ,那内层函数的 this 会受影响吗?(注意区别箭头函数)

function foo () {

console.log(this.a)

return function() {

console.log(this.a)

}

}

var obj = { a: 1 }

var a = 2

foo.call(obj)()

foo.call(obj) : 第一层函数 foo 通过 call 将 this 指向 obj ,打印 1 ;第二层函数为匿名函数,默认绑定,打印 2 。

答案

题目4.8:对象中的call

把上面的代码移植到对象中,看看会发生怎样的变化?

var obj = {

a: ‘obj’,

foo: function () {

console.log(‘foo:’, this.a)

return function () {

console.log(‘inner:’, this.a)

}

}

}

var a = ‘window’

var obj2 = { a: ‘obj2’ }

obj.foo()()

obj.foo.call(obj2)()

obj.foo().call(obj2)

看着这么多括号,是不是感觉有几分头大。没事,咱们来一层一层分析:

obj.foo()()

obj.foo()

foo:obj

inner:window

obj.foo.call(obj2)()

题目4.7

obj.foo.call(obj2)

call

obj.foo

this

obj2

foo: obj2

inner:window

obj.foo().call(obj2)

题目4.5

foo: obj

call

this

obj2

inner: obj2

题目4.9:带参数的call

显式绑定一开始讲的时候,就谈过 call/apply 存在传参差异,那咱们就来传一下参数,看看传完参数的this会是怎样的美妙。

var obj = {

a: 1,

foo: function (b) {

b = b || this.a

return function © {

console.log(this.a + b + c)

}

}

}

var a = 2

var obj2 = { a: 3 }

obj.foo(a).call(obj2, 1)

obj.foo.call(obj2)(1)

要注意 call 执行的位置:

  • obj.foo(a).call(obj2, 1) :

  • obj.foo(a) : foo的AO中b值为传入的a(形参与实参相统一),值为2,返回匿名函数fn

  • 匿名函数 fn.call(obj2, 1) : fn的this指向为obj2,c值为1

  • this.a + b + c = obj2.a + FooAO.b + c = 3 + 2 + 1 = 6

  • obj.foo.call(obj2)(1) :

  • obj.foo.call(obj2) : obj.foo的this指向obj2,未传入参数,b = this.a = obj2.a = 3;返回匿名函数fn

  • 匿名函数 fn(1) : c = 1,默认绑定,this指向window

  • this.a + b + c = window.a + obj2.a + c = 2 + 3 + 1 = 6

答案

麻了吗,兄弟们。进度已经快过半了,休息一会,争取把 this 一次性吃透。

5.显式绑定扩展


上面提了很多 call/apply 可以改变 this 指向,但都没有太多实用性。下面来一起学几个常用的 call与apply 使用。

题目5.1:apply求数组最值

JavaScript中没有给数组提供类似max和min函数,只提供了 Math.max/min ,用于求多个数的最值,所以可以借助apply方法,直接传递数组给 Math.max/min

const arr = [1,10,11,33,4,52,17]

Math.max.apply(Math, arr)

Math.min.apply(Math, arr)

题目5.2:类数组转为数组

ES6 未发布之前,没有 Array.from 方法可以将类数组转为数组,采用 Array.prototype.slice.call(arguments) 或 [].slice.call(arguments) 将类数组转化为数组。

题目5.3:数组高阶函数

日常编码中,我们会经常用到 forEach、map 等,但这些数组高阶方法,它们还有第二个参数 thisArg ,每一个回调函数都是显式绑定在 thisArg 上的。

例如下面这个例子

const obj = {a: 10}

const arr = [1, 2, 3, 4]

arr.forEach(function (val, key){

console.log(${key}: ${val} --- ${this.a})

}, obj)

答案

0: 1 — 10

1: 2 — 10

2: 3 — 10

3: 4 — 10

关于数组高阶函数的知识可以参考: JavaScript之手撕高阶数组函数

6.new绑定


使用 new 来构建函数,会执行如下四部操作:

  1. 创建一个空的简单 JavaScript 对象(即 {} );

  2. 为步骤1新创建的对象添加属性 __proto__ ,将该属性链接至构造函数的原型对象 ;

  3. 将步骤1新创建的对象作为 this 的上下文 ;

  4. 如果该函数没有返回对象,则返回 this 。

关于new更详细的知识,可以参考: JavaScript之手撕new [7]

通过new来调用构造函数,会生成一个新对象,并且把这个新对象绑定为调用函数的this。

题目6.1:new绑定

function User(name, age) {

this.name = name;

this.age = age;

}

var name = ‘Tom’;

var age = 18;

var zc = new User(‘zc’, 24);

console.log(zc.name)

答案

zc

题目6.2:属性加方法

function User (name, age) {

this.name = name;

this.age = age;

this.introduce = function () {

console.log(this.name)

}

this.howOld = function () {

return function () {

console.log(this.age)

}

}

}

var name = ‘Tom’;

var age = 18;

var zc = new User(‘zc’, 24)

zc.introduce()

zc.howOld()()

这个题很难不让人想到如下代码,都是函数嵌套,具体解法是类似的,可以对比来看一下啊。

const User = {

name: ‘zc’;

age: 18;

introduce = function () {

console.log(this.name)

}

howOld = function () {

return function () {

console.log(this.age)

}

}

}

var name = ‘Tom’;

var age = 18;

User.introduce()

User.howOld()()

  • zc.introduce() : zc是new创建的实例,this指向zc,打印 zc

  • zc.howOld()() : zc.howOld()返回一个匿名函数,匿名函数为默认绑定,因此打印18(阿包永远 18 )

答案

zc

18

题目6.3:new界的天王山

new 界的天王山,每次看懂后,没过多久就会忘掉,但这次要从根本上弄清楚该题。

接下来一起来品味品味:

function Foo(){

getName = function(){ console.log(1); };

return this;

}

Foo.getName = function(){ console.log(2); };

Foo.prototype.getName = function(){ console.log(3); };

var getName = function(){ console.log(4); };

function getName(){ console.log(5) };

Foo.getName();

getName();

Foo().getName();

getName();

new Foo.getName();

new Foo().getName();

new new Foo().getName();

  1. 预编译

GO = {

Foo: fn(Foo),

getName: function getName(){ console.log(5) };

}

  1. 分析后续执行
  • Foo.getName() : 执行Foo上的getName方法,打印 2

  • getName() : 执行GO中的getName方法,打印 4

  • Foo().getName()

// 修改全局GO的getName为function(){ console.log(1); }

getName = function(){ console.log(1) }

// Foo为默认绑定,this -> window

// return window

return this

复制代码

  • Foo().getName() : 执行window.getName(),打印 1

  • Foo() 执行

  • getName() : 执行GO中的getName,打印 1

  1. 分析后面三个打印结果之前,先补充一些运算符优先级方面的知识(图源: MDN [8] )

从上图可以看到,部分优先级如下: new(带参数列表) = 成员访问 = 函数调用 > new(不带参数列表)

  1. new Foo.getName()

首先从左往右看: new Foo 属于不带参数列表的new(优先级 19 ), Foo.getName 属于成员访问(优先级 20 ), getName() 属于函数调用(优先级 20 ),同样优先级遵循从左往右执行。

  • Foo.getName 执行,获取到Foo上的 getName 属性

  • 此时原表达式变为 new (Foo.getName)() , new (Foo.getName)() 为带参数列表(优先级 20 ), (Foo.getName)() 属于函数调用(优先级 20 ),从左往右执行

new (Foo.getName)()

2

Foo.getName()

这里有一个误区:很多人认为这里的 new 是没做任何操作的的,执行的是函数调用。那么如果执行的是 Foo.getName() ,调用返回值为 undefined , new undefined 会发生报错,并且我们可以验证一下该表达式的返回结果。

console.log(new Foo.getName())

// 2

// Foo.getName {}

可见在成员访问之后,执行的是 带参数列表格式的new 操作。

  1. new Foo().getName()

步骤4

new Foo()

Foo

Foo

getName

Foo.prototype.getName

3

  1. new new Foo().getName()

从左往右分析: 第一个new不带参数列表(优先级 19 ), new Foo() 带参数列表(优先级 20 ),剩下的成员访问和函数调用优先级都是 20

  • new Foo() 执行,返回一个以 Foo 为构造函数的实例

Foo

Foo.prototype

getName

new (new Foo().getName)()

Foo.prototype.getName()

3

  1. new Foo.getName()  与  new new Foo().getName() 区别:
  • new Foo.getName() 的构造函数是 Foo.getName

  • new new Foo().getName() 的构造函数为 Foo.prototype.getName

测试结果如下:

foo1 = new Foo.getName()

foo2 = new new Foo().getName()

console.log(foo1.constructor)

console.log(foo2.constructor)

输出结果:

2

3

ƒ (){ console.log(2); }

ƒ (){ console.log(3); }

通过这一步比较应该能更好的理解上面的执行顺序。

答案

兄弟们,革命快要成功了,再努力一把,以后this都小问题啦。

7.箭头函数


箭头函数没有自己的 this ,它的 this 指向外层作用域的 this ,且指向函数定义时的 this 而非执行时。

this指向外层作用域的this

this

this

  1. 指向函数定义时的this而非执行时 :  JavaScript 是静态作用域,就是函数定义之后,作用域就定死了,跟它执行时的地方无关。更详细的介绍见 JavaScript之静态作用域与动态作用域 [9] 。

题目7.1:对象方法使用箭头函数

name = ‘tom’

const obj = {

name: ‘zc’,

intro: () => {

console.log('My name is ’ + this.name)

}

}

obj.intro()

上文说到,箭头函数的 this 通过作用域链查到, intro 函数的上层作用域为 window 。

答案

My name is tom

题目7.2:箭头函数与普通函数比较

name = ‘tom’

const obj = {

name: ‘zc’,

intro:function () {

return () => {

console.log('My name is ’ + this.name)

}

},

intro2:function () {

return function() {

console.log('My name is ’ + this.name)

}

}

}

obj.intro2()()

obj.intro()()

  • obj.intro2()() : 不做赘述,打印 My name is tom

obj.intro()()

obj.intro()

this

this

obj

My name is zc

题目7.3:箭头函数与普通函数的嵌套

name = ‘window’

const obj1 = {

name: ‘obj1’,

intro:function () {

console.log(this.name)

return () => {

console.log(this.name)

}

}

}

const obj2 = {

name: ‘obj2’,

intro: ()=> {

console.log(this.name)

return function() {

console.log(this.name)

}

}

}

const obj3 = {

name: ‘obj3’,

intro: ()=> {

console.log(this.name)

return () => {

console.log(this.name)

}

}

}

obj1.intro()()

obj2.intro()()

obj3.intro()()

obj1.intro()()

题目7.2

obj1,obj1

obj2.intro()()

obj2.intro()

this

this

window

window,window

obj3.intro()()

obj3.intro()

obj2.intro()

intro

this

window

window,window

答案

obj1

obj1

window

window

window

window

题目7.4:new碰上箭头函数

function User(name, age) {

this.name = name;

this.age = age;

this.intro = function(){

console.log('My name is ’ + this.name)

},

this.howOld = () => {

console.log('My age is ’ + this.age)

}

}

var name = ‘Tom’, age = 18;

var zc = new User(‘zc’, 24);

zc.intro();

zc.howOld();

zc

new User

User

this

zc

  • zc.intro() : 打印 My name is zc

  • zc.howOld() :  howOld 为箭头函数,箭头函数 this由外层作用域决定,且指向函数定义时的this ,外层作用域为 User , this 指向 zc ,打印 My age is 24

题目7.5:call碰上箭头函数

箭头函数由于没有 this ,不能通过 call\apply\bind 来修改 this 指向,但可以通过修改外层作用域的 this 来达成间接修改

var name = ‘window’

var obj1 = {

name: ‘obj1’,

intro: function () {

console.log(this.name)

return () => {

console.log(this.name)

}

},

intro2: () => {

console.log(this.name)

return function () {

console.log(this.name)

}

}

}

var obj2 = {

name: ‘obj2’

}

obj1.intro.call(obj2)()

obj1.intro().call(obj2)

obj1.intro2.call(obj2)()

obj1.intro2().call(obj2)

obj1.intro.call(obj2)()

call

this

obj2

obj2

this

this

obj2

obj1.intro().call(obj2)

obj1

call

this

this

obj1

obj1.intro2.call(obj2)()

call

window

window

window

obj1.intro2().call(obj2)

window

call

this

obj2

obj2

答案

obj2

obj2

obj1

obj1

window

window

window

obj2

8.箭头函数扩展


总结

this

this

this

this

  • 不可以用作构造函数,不能使用 new 命令,否则会报错

  • 箭头函数没有 arguments 对象,如果要用,使用 rest 参数代替

  • 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

call/apply/bind

this

this

  • 箭头函数没有 prototype 属性。

避免使用场景

  1. 箭头函数定义对象方法

const zc = {

name: ‘zc’,

intro: () => {

// this -> window

console.log(this.name)

}

}

zc.intro() // undefined

  1. 箭头函数不能作为构造函数

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Java)

《MySql面试专题》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySql性能优化的21个最佳实践》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySQL高级知识笔记》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

关注我,点赞本文给更多有需要的人
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
tro2.call(obj2)()

obj1.intro2().call(obj2)

obj1.intro.call(obj2)()

call

this

obj2

obj2

this

this

obj2

obj1.intro().call(obj2)

obj1

call

this

this

obj1

obj1.intro2.call(obj2)()

call

window

window

window

obj1.intro2().call(obj2)

window

call

this

obj2

obj2

答案

obj2

obj2

obj1

obj1

window

window

window

obj2

8.箭头函数扩展


总结

this

this

this

this

  • 不可以用作构造函数,不能使用 new 命令,否则会报错

  • 箭头函数没有 arguments 对象,如果要用,使用 rest 参数代替

  • 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

call/apply/bind

this

this

  • 箭头函数没有 prototype 属性。

避免使用场景

  1. 箭头函数定义对象方法

const zc = {

name: ‘zc’,

intro: () => {

// this -> window

console.log(this.name)

}

}

zc.intro() // undefined

  1. 箭头函数不能作为构造函数

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-SQD6RFe5-1713802324773)]

[外链图片转存中…(img-69oMjiqt-1713802324773)]

[外链图片转存中…(img-wHozwyM4-1713802324774)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Java)

[外链图片转存中…(img-ftfXa0RO-1713802324774)]

《MySql面试专题》

[外链图片转存中…(img-OanHaDnM-1713802324774)]

[外链图片转存中…(img-j4cXvxdB-1713802324775)]

《MySql性能优化的21个最佳实践》

[外链图片转存中…(img-JdUbWBal-1713802324775)]

[外链图片转存中…(img-PUt3rvdG-1713802324775)]

[外链图片转存中…(img-BoYhOSL7-1713802324775)]

[外链图片转存中…(img-rGEWiq4d-1713802324775)]

《MySQL高级知识笔记》

[外链图片转存中…(img-E7mQJO6X-1713802324775)]

[外链图片转存中…(img-qVGEMIdI-1713802324776)]

[外链图片转存中…(img-AS8XVzS7-1713802324776)]

[外链图片转存中…(img-z1uHY99v-1713802324776)]

[外链图片转存中…(img-hRfSAjoH-1713802324776)]

[外链图片转存中…(img-oGkoGgtN-1713802324776)]

[外链图片转存中…(img-guhyn6zv-1713802324776)]

[外链图片转存中…(img-pJElSih6-1713802324777)]

[外链图片转存中…(img-EQqJleZt-1713802324777)]

[外链图片转存中…(img-Lwst12oE-1713802324777)]

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

[外链图片转存中…(img-Au9LfQGO-1713802324777)]

关注我,点赞本文给更多有需要的人
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值