立刻又到年末了,跳槽的季节。javascript
我又想起来曾经准备面试
的情景, 各类搜集资料, 整理, 面试, 再整理, 十分的辛苦。前端
其实,不管面试哪家公司, 基础
都是免不了的.java
以前就有整理一下这些资料的想法,不过本身比较懒, 一只没有动手。面试
最近在作公众号,就想着干脆搞一搞,把这些基础知识整理一下,之后本身也能看。segmentfault
恰好国庆在家看了ES6
相关的东西, 这一篇就从ES6
开始吧。微信
var, let, const
这三个东西, 常常会被问到。 模块化
汇总一下,基本上就是:函数
var, let, const
有什么区别
?变量提高
(hosting) ?TDZ
?首先, 咱们先总体的看下区别
:学习
针对这几点, 咱们一个个看。ui
首先, 咱们仍是先了解一下变量提高
.
看个例子:
console.log(a) // undefined var a = 1
这里咱们能够看到, 第一行中的a虽然还没声明, 可是咱们用起来却不会报错。 这种状况, 就是声明的提高。
其实也就是:
var a console.log(a) // undefined a = 1
可是, 若是是换成let
, 状况就不同了:
要理解这个现象, 首先须要搞清楚提高的本质, 理解建立 javascript 变量的三个步骤
:
建立
初始化
赋值
为了便于理解, 咱们先看看var
的 建立、初始化和赋值
过程:
function foo(){ var x = 1 var y = 2 } foo()
执行foo 时, 会有一些过程(部分过程):
也就是说 va
声明, 会在代码执行以前就将 建立变量
,并将其初始化为 undefined
。
这就解释了为何在 var x = 1 以前 console.log(x) 会获得 undefined
。
接下来看 let 声明的「建立、初始化和赋值」过程
// ... { let x = 1; x = 2 }
咱们看一下过程:
let
声明的变量,在环境中建立
这些变量这就解释了为何在 let x 以前使用 x 会报错:
let x = 'global' { console.log(x) // Uncaught ReferenceError: x is not defined let x = 1 }
缘由有两个
TDZ
, tempory dead zone, 暂时死区)说到这里, 就都清楚了:
function 也是相似的,并且function 的「建立」「初始化」和「赋值」都被提高了。
这一点, 感兴趣的朋友能够本身实验一下。
算了, 直接给个例子吧:
<script> bar() function bar(){ console.log(2) } </script>
JS 引擎会有一下过程:
function(){ console.log(2) }
。也就是说 function 声明会在代码执行以前就「建立、初始化并赋值」。
这里作一下简单的总结:
函数提高优先于变量提高
. 函数提高
会把整个函数挪到做用域顶部
,变量提高
只会把声明
挪到做用域顶部
。var
存在提高
,咱们能在声明以前
使用。let
, const
由于存在暂时性死区
,不能在声明前使用
。var
在全局做用域
下声明变量, 会致使变量挂载在window
上, 而另外二者不会
。let
和 const
的做用基本一致,可是后者声明的变量不能再次赋值。这个也是 ES6 里比较好用的feature, 咱们天天也都会用到。
箭头函数是 ES6 中新的函数定义形式:
function name(arg1, arg2) {} // 可使用 (arg1, arg2) => {} // 来定义。
箭头函数, 一方面看起来比较简洁, 另外一方面, 之解决ES5时代,this
的问题.
看个例子:
function fn() { console.log(this) // {a: 100} ,该做用域下的 this 的真实的值 var arr = [1, 2, 3] // ES5 arr.map(function (item) { console.log(this) // window }) // 箭头函数 arr.map(item => { console.log(this) // {a: 100} 这里打印的就是父做用域的 this }) } fn.call({a: 100})
模块化的好处是十分明显的:
解决命名冲突
提供复用性
提升代码可维护性
ES6 以前也有模块化的方案: AMD, CMD
, 就简单的提一下, 不是本文讨论的主要内容。
// AMD define(['./a', './b'], function(a, b) { a.do() b.do() }) // CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() })
也有一种IIFE
的 形式:
(function(globalVariable){ // 造成一个独立的做用域,不会污染全局 // ... })(globalVariable)
CommonJS 最先是 Node.js 在使用,目前也仍然普遍使用。
看个例子:
// a.js module.exports = { a: 1 } // b.js var module = require('./a.js') module.a // 1
ES Module 是原生实现的模块化方案, 提供了一种新的, 能够文件做为模块的开发方式。
使用方式就是咱们常见的:
// a.js export function a() {} export default function() {} //b.js import XXX from './a.js' import { XXX } from './a.js'
若是只是输出一个惟一的对象,使用export default便可:
// util1.js export default { a: 100 } // index.js 文件 import obj from './util1.js' console.log(obj) // { a: 100 }
若是想要输出许多个对象,就不能用 default了,并且 import 时候要加 { ... },代码以下:
// foo.js export function fn1() { alert('fn1') } export function fn2() { alert('fn2') } // index.js import { fn1, fn2 } from './foo.js' fn1() fn2()
class 其实一直是js的保留字,直到 ES6 才正式用到。
(js中并不存在类,class 只是个语法糖。本质上仍是函数, 其实就是要模拟面向对象的语法, 你懂的)
ES6 的 class 就是取代以前构造函数
初始化对象的形式,从语法
上更加接近面向对象
的写法。
例如:
// ES5 function MathHandle(x, y) { this.x = x; this.y = y; } MathHandle.prototype.add = function () { return this.x + this.y; }; var method = new MathHandle(1, 2); console.log(method.add())
ES6 class 的写法:
class MathHandle { constructor(x, y) { this.x = x; this.y = y; } add() { return this.x + this.y; } } const method = new MathHandle(1, 2); console.log(method.add())
注意如下几点:
class Name {...}
这种形式,和函数的写法彻底不同.constructor
函数中,constructor
即构造器,初始化实例时默认执行.add() {...}
这种形式,并无function
关键字.使用 Class 来实现继承就更加简单了,至少比构造函数实现继承简单不少:
// 动物 function Animal() { this.eat = function () { console.log('animal eat') } } // 狗 function Dog() { this.bark = function () { console.log('dog bark') } } Dog.prototype = new Animal() var husky = new Dog() husky.bark() // dog bark
ES6 写法:
class Animal { constructor(name) { this.name = name } eat() { console.log(`${this.name} eat`) } } class Dog extends Animal { constructor(name) { super(name) this.name = name } bark() { console.log(`${this.name} say`) } } const husky = new Dog('哈士奇') husky.bark()
注意如下两点:
extends
便可实现继承,更加符合经典面向对象语言的语法.constructor
必定要执行super()
,调用父类的constructor
.以上这几个方面都是面试中常常问的,ES6的内容远远不知这些, 好用的特性还有不少, 好比:
...
」 操做符这里就不一一介绍了。
「 ...
」 操做符 这个能够参考个人这篇文章:
ES6 面试问的比较多的
大概就是以上这几点, 可能有所纰漏, 后面再作补充吧。
但愿对你们有所帮助。
今天是楼主节后第一天上班, 不在状态。
说个最尴尬的事情吧, 今天要填2019的绩效自评, 其中有一项:
公司在哪些方面能帮助你成长?
原本是一个很正常的问题:
我是这么写的:
写完笑了笑, 跟同事调侃了一下, 可不得加薪吗。 说完回头我就直接点了提交。
提交完感受哪里不大对?
就这么提交了 ???
卧, 惧怕, 卧, 我干了什么
反正也不能改了, 就这样吧。
文中如有纰漏, 还请各位大佬指正。
若是你以为内容有帮助能够关注下个人公众号 「 前端e进阶 」,一块儿学习成长
能够经过公众号菜单栏的联系我
, 加入咱们的微信群
, 一块儿愉快的玩耍。