当前位置:   article > 正文

4. 箭头函数和普通函数的区别(关键:this指向的区别),以及this指向的四种规则_箭头函数跟普通函数中的this指向

箭头函数跟普通函数中的this指向

目录

相关的问题:

最明显的区别:

(1)箭头函数的定义:

(2)普通函数的this指向:

(3)箭头函数的this指向:

1. 特性一:

2. 特性二:

(4)箭头函数为什么不能作为构造函数?

1. 箭头函数不能作为构造函数,而匿名函数可以作为构造函数。

2. 原因:

(6)箭头函数没有原型属性

(7)箭头函数不绑定arguments,取而代之用rest参数…解决

  1. arguments

2. 用rest参数…解决

3. rest参数的用法相对于arguments的优点:

(8)this指向的四种规则

1. 默认的绑定规则

2. 隐式绑定规则:谁调用this就指向谁(参数赋值导致隐式丢失)

3. 显示绑定:call、apply、bind(用来绑定this指向)

4. new 绑定(优先级 4>3>2>1)

(9)总结

1)普通函数和箭头函数的区别:

2)箭头函数的注意事项:


相关的问题:

1. ES6 的箭头函数和以前的普通函数的区别?

2. 箭头函数可以作为构造函数吗?为什么不能作为构造函数呢?

3. 箭头函数没有原型对象?

最明显的区别:

    1. 箭头函数(箭头函数表达式**的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

  • 写法简洁;
  • 没有this指向,this永远来自其上下文的 this;
  • 任何方法都改变不了其指向,如call(), bind(), apply();
  • 箭头函数不能用作构造器,和 new一起用会抛出错误
  • 箭头函数没有prototype(原型)属性
  • 不绑定arguments,该对象在函数体内不存在,如果要用的话,可以用rest参数代替;
  • 箭头函数和匿名函数是有区别的(this指向的不同)。例:调用函数obj1.getAge(2017)和调用obj2.getAge(2017)

  2.普通函数的

  • this指向调用它的那个对象

 

(1)箭头函数的定义:

使用方法:

其中()内是要带入的参数,{}内是要执行的语句。

 

定义:

箭头函数是函数式编程的一种体现,函数式编程将更多的关注点放在输入和输出的关系,省去了过程的一些因素,

因此箭头函数中没有自己的this,arguments,new target(ES6)和 super(ES6)。

箭头函数相当于匿名函数,因此不能使用new来作为构造函数使用。

 

三种定义方式:{} 、()、不加括号


 

(2)普通函数的this指向:

总结1:

  • 普通函数的this总是指向它的直接调用者。

  • 在严格模式下,没找到直接调用者,则函数中的this是undefined。

  • 在默认模式下(非严格模式),没找到直接调用者,则函数中的this指向window。

例如:

          

总结2:

  • 对于方法(即通过对象调用了该函数),普通函数中的this总是指向它的调用者

  • 对于一般函数this指向全局变量(非严格模式下)或者undefined(严格模式下)。在下例中setTimeout中的function未被任何对象调用,因此它的this指向还是window对象。因此,这也可以总结成:javascript 的this 可以简单的认为是后期绑定,没有地方绑定的时候,默认绑定window或undefined。

例如:

你可能会认为此时的输出应该为1,但是结果却是undefined。因为此时this的指向是全局的window对象。

解决方法1:

在setTimeout函数的外部,也就是上层函数foo内部通过将this值(this指向当前的对象)赋给一个临时变量来实现。

解决方法2:

通过bind()来绑定this。

(3)箭头函数的this指向:

箭头函数的 this 绑定是无法通过 callapplybind 被修改的,且因为箭头函数没有构造函数 constructor,所以也不可以使用 new 调用,即不能作为构造函数

普通函数:非严格模式下,默认绑定的this指向全局对象window严格模式下this指向undefined

箭头函数:严格模式和非严格模式下它的this都会指向全局对象window

1. 特性一:

准确来说,箭头函数中没有this,箭头函数的this指向取决于外层作用域中的this,外层作用域或函数的this指向谁,箭头函数中的this便指向谁。

示例中,箭头函数的this指向,等于 其外层函数fn的this指向,即obj1

(函数fn的返回值为箭头函数,并赋值给bar,因此bar指向的是箭头函数,故bar.call(obj2)不能修改箭头函数的this指向)

2. 特性二:

一旦箭头函数的this绑定成功,也无法被再次修改(this始终指向其父级作用域中的this任何方法都改变不了其指向,如call(), bind(), apply()。)

解决:

可以修改外层函数this指向达到间接修改箭头函数this的目的。

 

(4)箭头函数为什么不能作为构造函数?

1. 箭头函数不能作为构造函数,而匿名函数可以作为构造函数。

例如:

2. 原因:

1)new执行过程:

  1. new会在内存中创建一个新的空对象
  2. new 会让this指向这个新的对象
  3. 执行构造函数 目的:给这个新对象加属性和方法
  4. new会返回这个新对象
  1. function Person() {
  2.     var this = { //1、this 执行新的空对象
  3.         __proto__: Person.prototype
  4.     }
  5.     this.name = name //2、给新对象添加属性和方法
  6.     this.age  = age
  7.     return this //3、返回新对象
  8. }
  9. var person = new Person()

2)箭头函数:

箭头函数没有构造函数 constructor。

由于箭头函数没有自己的this,它的this来自上级作用域。并且不能通过修改箭头函数的this(只能通过修改其上级作用域的this进行改变)。

因此我们不能通过new来改变箭头函数Person的this指向,其指向仍为window,故箭头函数不能作为构造函数。

3)匿名函数:

匿名函数可以通过new修改其this指向,因此可以作为构造函数。

(6)箭头函数没有原型属性

(7)箭头函数不绑定arguments,取而代之用rest参数…解决

  1. arguments

每一个函数都有一个arguments对象,用于访问未知或可变的函数参数,通常我们把它当作数组使用,

但它却不是数组,不能对arguments对象使用其他JavaScript数组方法,如pop,push,slice等。是对象类型

例1 普通函数:arguments存放了传入的实参

例1 箭头函数:报错

   

2. 用rest参数…解决

1)定义

ECMAScript 6引入了一个新功能,Rest参数(扩展运算符...):

表示一个未知数量的参数作为函数中的一个数组。它不仅将额外的参数表示为数组,还解决了arguments对象的许多问题。

如果最后命名的函数参数以…(三个点)作为前缀,那么它将成为函数的rest参数。

2)优势:

JavaScript函数的rest参数是纯JavaScript数组

a(其中a可以随意命名)是函数add的rest参数,因为它是唯一的命名参数,且也以…(三个点)作为前缀。

由于rest参数是JavaScript数组,所以你可以对rest参数a执行诸如push,pop等操作

3)注意:

rest必须是函数的最后一位参数;

函数的length属性,不包括 rest 参数;

3. rest参数的用法相对于arguments的优点:

  1. 箭头函数和普通函数都可以使用。

  2. 更加灵活,接收参数的数量完全自定义。

  3. 可读性更好,参数都是在函数括号中定义的,不会突然出现一个arguments,以前刚见到的时候,真的好奇怪了!

  4. rest是一个真正的数组,可以使用数组的API。

 

(8)this指向的四种规则

主要看函数执行时的this

1. 默认的绑定规则

指向window,即this和window指向的是同一个对象

1.1 全局中:

console.log(this === window); // true

1.2 函数的独立调用(this默认指向window):

默认是挂载到window上的,

test() 相当于 window.test() 

2. 隐式绑定规则:谁调用this就指向谁(参数赋值导致隐式丢失)

2.1 简单的方法调用 this指向

2.2 含有嵌套函数的this指向

每一个函数在执行时都会有自身的不同的this(他们的this指向是否相等,是由函数的执行方式决定的)(函数如果不执行,函数中的this没有任何意义),

所以下面例子中这两个函数的this不同(只需要看这两个函数的调用方式)

2.3 obj.foo()()的this指向(有返回函数)

2.4 变量赋值(赋值导致隐式丢失,即转化为了独立调用)

将obj.foo赋值给bar,调用bar() 。this指向window

2.5 参数赋值

obj.foo 表示函数foo =》 bar(obj.foo)相当于 bar(foo)    =》  在函数bar中调用函数foo() ,独立调用  =》 故函数foo的this指向window

2.6 父函数有能力决定子函数的this指向

当函数为参数时,这个参数为回调函数

父函数指定子函数的this指向

3. 显示绑定:call、apply、bind(用来绑定this指向)

1. 四种调用方式,分别调用foo函数(call、apply、bind 传参的方式不同

其中call、apply、bind 参数中的obj:表示绑定的this指向

2.

3. null 和 undefined 不能作为this指向,如果作为this指向,则绑定失败,默认this指向为window。

例如:

4. new 绑定(优先级 4>3>2>1)

1. new一个构造器,主要有三步:

• 创建一个空对象,将它的引用赋给 this(即this指向这个新对象),继承函数的原型。
• 通过 this 将属性和方法添加至这个对象(执行构造函数中的代码)
• 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)

相当于下面过程:

2. new 绑定

构造调用创建了一个新对象echo,而在函数体内,this将指向新对象echo上(可以抽象理解为新对象就是this)。

3. 用new创建person对象实例

结果说明了:用new的创建实例,构造函数作用域赋给了person1(通过构造函数的this指针),所以window。sayname自然就会提示错误。

  1. var person1=new Person("yyh","24","web前端")
  2. person1.sayname();//弹出对话框,显示“yyh” (sayname是Person对象中的方法)
  3. window.sayname()//提示错误,对象不支持此方法

4. 将构造函数作为普通函数来调用

结果说明了:不使用new创建构造函数的实例时,this指向的是全局作用域即window对象,所以window.sayname()显示的就是yyh2。可以说明Person的属性和方法都被添加到了window对象。

  1. Person("yyh2","25","web前端"
  2. window.sayname();//显示“yyh2
  3. Person.sayname();//提示错误;

5. 在另外一个对象的作用域中调用(修改this指向)

call函数是指在对象0的作用域中调用Person函数,即绑定Person函数的this指向为o。

  1. var o=new Object();
  2. Person.call(o,"yyh2","25","web前端");
  3. o.sayname();//也显示yyh2

6. 构造函数也是函数。与函数的区别在哪里呢?很显然在于调用它们的方式不同。

      任何函数,只要通过new操作符来调用,那么他就可以作为构造函数

      任何函数,如果不通过new操作符来调用,他跟普通的函数没有区别

(9)总结

1)普通函数和箭头函数的区别:

(1)箭头函数不能作为构造函数,不能使用new(箭头函数没有构造函数 constructor)。

(2)箭头函数不绑定arguments,取而代之用rest参数...解决。

(3)this的作用域不同,箭头函数不绑定this,会捕获其外层第一个普通函数的this值,作为自己的this值。

(4)箭头函数本身的this指向不能改变,但可以修改它要继承的对象的this。

(5)箭头函数没有原型属性,所以箭头函数本身没有this

(6)箭头函数不能当做Generator函数,不能使用yield关键字。(下面链接详细介绍了Generator函数)

https://blog.csdn.net/fu983531588/article/details/89482179?utm_source=app&app_version=4.6.1

(7)箭头函数不支持new.target(new.target是ES6新引入的属性,用于确定构造函数是否为new调用的)

(8)箭头函数不支持重命名函数参数,普通函数的函数参数支持重命名

(9)箭头函数相对于普通函数语法更简洁优雅

2)箭头函数的注意事项

  1. 箭头函数一条语句返回对象字面量,需要加括号

   2. 箭头函数在参数和箭头之间不能换行

     

   3. 箭头函数的解析顺序相对||靠前

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/63533
推荐阅读
相关标签
  

闽ICP备14008679号