1.class声明的函数会有变量提升,但是不会赋值(即进入了暂时性死区,类似let和const声明的变量),而function声明的函数既会提示,也会初始化
暂时性死区:
只要块级作用域内存在
let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
上面代码中,存在全局变量
tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。ES6 明确规定,如果区块中存在
let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用
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()