ES6中,箭头函数与常规函数

###就不发表个人获奖感言了,直接开始吧,真的被自己菜到了,虽然我以前也不记记不住这玩意~

正文开始——

常规函数:使用function关键字定义,可声明为函数声明和函数表达式

函数声明

good("彩虹海")
//你可以在它声明之前调用,函数声明可以提升
function good(name){
    return "Hello,"+name
}

函数表达式

hello("彩虹海")/*错误示范**/
//这里是无法调用的,会提示说:Cannot access 'set' before initialization,因为它不可以被提升
//只能在被定义后才能被调用
const hello = function(name){
    return "Hello,"+name
}
//这里可能会有人问function后面为什么没有函数名,因为函数表达式可以是匿名函数或具名函数表达式
hello("彩虹海")

常规函数的核心特征

1、动态的this绑定

常规函数的this值取决于调用方式,而非定义时的环境

默认绑定:当直接调用时,非严格模式(这个观念会在下一个文章里说明,也是下一个文章的标题)下this指向全局对象(如游览器中的window),严格模式下为underfined。

function showTip(){
    console.log(this)
}
showTip()
//这里在非严格模式下会打印window

隐式绑定:作为对象方法调用时,this指向对象

const obj = {
    value:"1",
    getValue:function(){
        return this.value //this指向obj
    }
}
console.log(obj.getValue())//1

显式绑定:通过call、apply或bind强制指定this

function logThis(a,b,c){
    console.log(this.name)
    console.log(a,b,c)
}
const person = {name:"123"}
logThis.call(person,"tian","di","ren") //123  换行  // tian  di  ren
logThis.apply(person,["tian","di","ren"])//123  换行  // tian  di  ren
const getBind = logThis.bind(person,"tian","di","ren")
getBind()//123  换行  // tian  di  ren
//实现效果可以通过调用控制台打印输出查看
/*
*这里简单了解下call、apply、bind的用法和区别
*/
call:立即触发函数调用,并显式指定this值,后面参数用逗号隔开
apply:立即触发函数调用,并显式指定this值,后面参数用[]包裹
bind:创建一个新的函数,永久绑定this值和部分参数,不立即执行

2、构造函数与new

常规函数可以用new关键字创建对象实例,此时函数被称为“构造函数”,负责初始化实例对象的属性和方法,为实例提供共享的行为模式。###句话我开始是非常不理解的,不看后面我的解释的话,不知道有没有小伙伴们愿意把你们的思考写在评论区呢?

function Peron(name){
    this.name=name
}
const name="彩虹海"
const logName = new Peron(name) 
//注意,构造函数的语法要求名称首字母必须大写,所以对应函数那里也要大写,不然会提示defined
console.log(logName.name)

//这里提出我的理解就是组件化开发,构造函数就是一个基础版的组件封装
//特性            构造函数                    组件封装
//作用       定义一类对象的通用结构和行为   定义一类UI的通用结构和行为
//复用方式   通过new生成多个实例           通过标签或者函数调用生成多个实例
//这里我理解构造函数是一个仅处理数据和行为的组件,而现代前端组件是扩展了UI和生命周期的超级构造函数

创建构造函数组件,我们需要配合prototype原型来使用,将构造函数内部的行为函数定义到prototype上 ,那么我们哪怕new了一百个实例,也只共用一个行为函数,这大大提高了内存的使用效率。

不过鉴于有了class语法,推荐使用class的语法来写。它本质是构造函数的语法糖,看起来更直观。

class User {
  constructor(name) {
    this.name = name;
  }

  // 方法自动挂载到原型
  sayHello() {
    console.log(`Hello, I'm ${this.name}`);
  }
}

const user = new User('Alice');

使用场景:当存在大量的类似的行为模式时

3、prototype原型和arguments对象

常规函数自动拥有prototype属性,用于实现基于原型的继承;常规函数内部可访问arguments对象,它是一个类数组对象,包含所有传入的参数。但它不是真正的数组,需要转换为数组才能使用数组的方法(Array.from(arguments))

常规函数部分使用场景

1、需要动态this的场景,例如需要this指向对象自身。

2、构造函数,构造函数必须使用常规函数创建实例

3、需要arguments对象的场景,例如处理不定数量参数

4、生成器函数(Generator),例如使用function*语法定义可暂停执行的函数

箭头函数:是ES6引入的语法糖,用=>定义,适用于简洁的表达式

基础语法

//单参数却单行返回时,省略{}和return
const quare = x => x + x;
console.log(quare(3))//6
//多参数或多行语句是,需用()包裹参数,{}包裹函数体
const sum = (a,b) => {
    const result = a + b;
    return result
}
console.log(sum(4,8)) //12
//如果要复制代码运行,注意命名规范,部分会重复命名。

核心特征

1、this绑定(无独立this),箭头函数的this继承自外层作用域,而非运行时调用方式

const obj  ={
    value:42,
    // 常规函数:this指向obj
    getValue:function(){
        return this.value;
    },
    //箭头函数:this继承外层(此处为全局)
    getValueEs:()=> this.value
}
console.log(obj.getValue())   //42 常规函数没有问题
console.log(obj.getValueEs()) //underfined 箭头函数this可能指向全局

那它在this这里的表现好像平平无奇啊,那它出现是为了解决什么问题呢?

const obj={
    value:42,
    start:function(){
        console.log("外层this value:"+this.value)
        setTimeout(function(){
            console.log("常规函数回调中的this value"+this.value)
        },1000)
    }
}
obj.start()
//是的,是为了解决回调中的this丢失问题;而为什么会丢失呢
//因为常规函数中,这里的this由调用方式决定,如setTimeout直接调用函数时,这里this
//默认指向的是全局对象

const obj={
    value:42,
    start:function(){
        console.log("外层this value:"+this.value)
        setTimeout(()=>{
            //箭头函数this继承外层this,这里指向obj。
            console.log("箭头函数回调中的this value"+this.value)
        },1000)
    }
}
obj.start()
//而箭头函数,通过词法作用域继承外层this,就避免了丢失问题

2、没有arguments对象:箭头函数无法访问自身的arguments,但可通过剩余参数(...rest)获取参数列表,剩余参数是一个真正的数组,替代了常规函数中的arguments,语法:...参数名,必须放在参数列表的最后。

没有prototype属性:箭头函数没有原型,无法用于原型继承。

不能作为构造函数:箭头函数没有[[Conctruct]]内部方法,无法用new调用。

不可用作Generator函数:箭头函数不能包含yield关键字,无法定义为生成器。

适用场景

1、需要固定this指向的回调函数

2、可以简化的函数

3、替代闭包保存this,常规函数在闭包中需要额外处理this指向,而箭头函数直接词法绑定this

回顾上方内容,我们可以了解到,箭头函数通过词法this解决了回调函数this丢失问题,通过简洁的语法,优化了函数式编程,提高了这些场景下的代码可读性和安全性。但是在需要动态this、构造函数或复杂功能时,常规函数仍是首选。

欢迎朋友们留言补充,我都会认真看完每一条评论的。文章中有很多地方的介绍都还是很表皮的,如果有写的不对的,希望大家能留言告诉我,我会在看到消息的第一时间进行处理。

【抱拳了老铁】

你可能感兴趣的:(es6,前端,ecmascript)