js中class声明的函数和function声明的函数有什么区别

1.class声明的函数会有变量提升,但是不会赋值(即进入了暂时性死区,类似let和const声明的变量),而function声明的函数既会提示,也会初始化

暂时性死区:

 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。 ----摘自 《阮一峰ES6标准入门》

使用function声明函数如下

    const testfn1 = new Testfn1() 
    console.log(testfn1) // Testfn{}
    function Testfn1 () { }

可以看到Testfn1被打印出来了,其实涉及到原理的话可以这样解释,浏览器在解析js代码时  在内存中会预先处理js代码,将函数声明放到内存中,代码的执行也是在内存中执行的。

使用class声明的函数如下

    const testfn2 = new Testfn2() // 'Testfn2' was used before it was defined.
    console.log(testfn2)

    class Testfn2 {
      constructor () {
        console.log('testfn2')
      }
    }

 这里产生了报错,Testfn2是在定义之前使用的,这与没有声明是不一样的,比如看下边这个

console.log(testfn3) // Error in created hook: "ReferenceError: testfn3 is not defined"

testfn3是未定义,这样一对比就提现出来了,class声明的函数是只声明,但未初始化(即未赋值)

 

2.使用class声明的函数,在其内部采用的是严格模式,而function声明的函数不是

使用function声明的方式

其中age1没有被声明,这里不会报错,注意不能去写console.log(age1) 如果打印的话是会报错的,未被定义,

    function Testfn1 () {
      age1 = 1
    }
    const testfn1 = new Testfn1()
    console.log(testfn1)

使用class声明的方式

    class Testfn2 {
      constructor () {
        age2 = 2 // Uncaught ReferenceError: age1 is not defined
      }
    }
    const testfn2 = new Testfn2()
    console.log(testfn2)

 

3.class的所有方法都是不可枚举的,而function声明的函数是可以枚举的。

function声明的形式

    function Testfn1(){

    }
    Testfn1.myname=function(){
      return 'jk'
    }
    Testfn1.prototype.age=function(){
      return 18
    }
    console.log(Object.keys(Testfn1)) // ["myname"]
    console.log(Object.keys(Testfn1.prototype)) // ["age"]

可以看出来所有的属性或者原型属性  都是可以被遍历得到的

class声明方式

    class Testfn2{
      static myname(){
        return 'sg'
      }
      age(){
        return 20
      }
    }
    console.log(Object.keys(Testfn2)) // []
    console.log(Object.keys(Testfn2.prototype)) // []

 

4.class的所有方法都没有原型对象prototype 不能通过new关键字来实例化

function方式

    function Testfn1(){

    }
    Testfn1.myname=function(){
      return 'jk'
    }

    Testfn1.prototype.age=function(){
      return 18
    }

    const testfn1 = new Testfn1()
    console.log(testfn1) // Testfn1 {}
    console.log(new testfn1.age()) // Testfn1.age {}

将age挂载到Testfn1的原型对象上,然后通过Testfn1的实例来调用age 并且通过new来实例化  发现是可以的

class方式

    class Testfn2{
      myname='lc'

      age(){
        return 20
      }
    }
    
    const testfn2=new Testfn2()
    console.log(testfn2)
    console.log(new testfn2.age()) // Uncaught TypeError: testfn2.age is not a constructor

其实很自然的  testfn2作为Testfn2的实例,它都访问不到age属性 当然也就不能被实例化了。

 

5.必须使用new来调用class

function声明的函数

    function Testfn1(){
      console.log('123')
    }

    const testfn1 =Testfn1() // 123

相当于一个普通函数的调用

class声明

    class Testfn2{
      constructor(){
        console.log('1234')
      }
    }

    const testfn2= Testfn2() // index.html:23 Uncaught TypeError: Class constructor Testfn2 cannot be invoked without 'new'

不允许直接调用

 

6.class内部无法重写类名

function方式

    function Testfn1(){
      Testfn1='Testfn10'
    }
    new Testfn1()

class方式

    class Testfn2{
      constructor(){
        Testfn2='Testfn20' // Uncaught TypeError: Assignment to constant variable
      }
    }
  new Testfn2()

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宋哈哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值