const 常量标识
const LIMIT = 10 // 常量一般是大写
const OBJ_MAP = {
a: 'A',
A: 'a'
}
const QUEUE = [1, 2, 3, 4, 5]
1、不允许反复声明赋值
// 变量重新赋值
var arg1 = '叶夜葉'
arg = '宵夜'
// 常量
// ES5
Object.defineProperty(window, 'arg2', {
valur: '宵夜'
writable: false
})
arg2 = '叶夜葉' // 报错
// ES6
const arg3 = '宵夜' // const不允许反复声明赋值
arg3 = '小可'
、、
2、 块级作用域
if(true) {
var arg1 = '宵夜'
}
console.log('arg1', arg1)
if(true) {
const arg2 = '宵夜'
}
console.log('arg2', arg2) // 报错 arg2 is not defined
3、 无变量提升
console.log(arg1)
var arg1 = '宵夜'
// 相当于
var arg1;
console.log(arg1)
arg1 = '宵夜'
// 无变量提升 - 先声明在使用
console.log(arg2)
const arg2 = '宵夜' // 报错 arg2 is not defined
// const 不在window中
const arg3 = '宵夜'
console.log(window.arg3) // 找不到
4、 let or const
- 引用类型
const obj = {
teacher: '宵夜',
leader: '小可'
}
obj.leader = '部部'
const arr = ['宵夜', '小可']
arr[0] = 'aaaa'
// const 在引用类型里面指的是地址
// ? 引用类型不让他修改
object.freeze(obj)
const obj2 = {
teacher: '宵夜',
leader: '小可',
zhuawa: ['黄小洋', '部部']
}
// !freeze只能冻结一层,嵌套引用类型需要遍历递归
// 面试题 不让修改引用类型所有属性
function deepFreeze(obj) {
// 2、确定主执行步骤
Object.freeze(obj)
// 3、逐级深入
(Object.key(obj) || []).forEach(key => {
let innerObj = obj[key];
if(typeof innerObj === 'object') {
// 1、 递归模式确定
deepFreeze(innerObj)
}
})
}
箭头函数
// 传统函数
function test(a, b) {
return a + b
}
const test2 = function(a, b) {
return a + b
}
箭头函数
// ES6
const test1 = (a, b) => {
return a + b
}
const test2 = (a, b) => a + b;
const test3 = x => {
// content
}
const test4 = () => {
// ....
}
上下文
let obj = {
teacher: '宵夜',
leader: '小可',
getTeacher: function() {
console.log('teacher is:', this.teacher)
return this.teacher
},
getLeader: () => {
console.log('leader is:', this.leader)
return this.leader
}
}
obj.getTeacher() // '宵夜'
obj.getLeader() // undefined
追问: 上下文形成的原因 箭头函数并不会形成独立上下文,内部this指向了window
场景1: dom操作cb时
const btn = document.querySelector('#btn')
btn.addEventListener('click', function() {
this.style.color = '#fff'
})
场景2:类操作
// 箭头函数无法成为完整构造类
function Obj(teacher, leader) {
this.teacher = teacher
this.leader = leader
}
const obj = (teacher, leader) => {
this.teacher = teacher
this.leader = leader
}
// 实例验证
const o1 = new obj('宵夜', '小可')
console.log(o1)
// 箭头函数无法构造原型方法 prototype
Obj.prototype.learn = function() {
console.log(this.teacher, this.leader)
}
obj.prototype.learn = () => {
console.log(this.teacher, this.leader)
}
箭头函数的参数特性 没有办法使用argument
const test = function(teacher) {
console.log(arguments)
}
const test = teacher => {
console.log(arguments)
}
class 使js更面向对象 - 类
// 传统对象 - function
function Course(teacher, leader) {
this.teacher = teacher;
this.leader = leader;
}
Course.prototype.getCourse = function() {
return `teacher is: ${this.teacher}, course: ${this.course}`
}
const course = new Course('宵夜', 'ES6')
course.getCourse();
// ES6
class Course {
// init 实例会默认执行
constructor(teacher, course) {
this.teacher = teacher
this.course = course
}
// 扩展方法
getCourse() {
return `teacher is:${this.teacher}, course:${this.course}`;
}
}
const course = new Course('宵夜', 'ES6')
course.getCourse()
追问 class的类型是什么
console.log(typeOf Course); // function
// class 其实是语法糖 后期baler打包会成为function
class的prototype
console.log(Course.prototype); // 有区分 但本职相同
属性定义 构造器 & 顶层定义 两种定义方式
class Course {
// init 实例会默认执行
constructor(teacher, course) {
this.teacher = teacher
this.course = course
}
// 扩展方法
getCourse() {
return `teacher is:${this.teacher}, course:${this.course}`;
}
get teacher() {
return this.teacher
}
set teacher(val) {
// 留有空间
this.teacher = val
}
}
js 如何建立私有属性
class Course {
// init 实例会默认执行
constructor(teacher, course) {
this._teacher = teacher
this.course = course
}
// 扩展方法
getCourse() {
return `teacher is:${this.teacher}, course:${this.course}`;
}
get teacher() {
return this._teacher
}
}
// 修改只读变量,会报错么 - 无法修改但是不会报错
// js 如何建立一个私有属性
class Course {
constructor(teacher, course) {
this._teacher = teacher;
// 在constructor作用域内定义一个局部变量
let _course = 'es6'
// 内部通过闭包的形式去暴露该变量
this.getCourse = () => {
return _course
}
}
}
class Course {
#course = 'es6'
constructor(teacher, course) {
this._teacher = teacher
}
get course() {
return this.#course
}
set course(val) {
if(val) {
this.#course = val
}
}
}
// 3、封装核心 - 适配器模式
class utils {
constructor(core) {
this._main = core
this._name = 'my-utils'
}
get name() {
return {
...this._main.name,
name: `utils is ${this._name}`
}
}
set name(val) {
this._name = val
}
}
静态方法 - 直接挂载在类上的方法无需实例化获取
// ES5
function Course() {
// ....
}
Course.ring = function() {
//...
}
// ES6
class Course {
constructor() {
// ....
}
static ring() {
}
}
继承
// ES5继承
function Course() {
// ...
}
Course.ring = function() {
// ...
}
Course.prototype.send = function() {
// ...
}
function Child() {
Course.call(this, '宵夜', 'ES5')
this.ring = function() {
// ...
}
}
Child.prototype = Course.prototype
// es6
class Course {
constructor() {
//...
}
static ring() {
// ...
}
send() {
// ...
}
}
// 工厂模式
class Child extends Course {
constructor() {
siper('宵夜', 'ES6')
}
send() {
// ...
}
}
key解构
const zhaowa = {
teacher: {
teacher: {
name: '',
age: 30
},
leader: '',
name: 'es6'
}
}
// 别名
const {
teacher: {
name,
age
},
leader,
name: className
} = zhaowa
追问解构使用场景
1、形参结构
const sum = arr => {
let res = 0;
arr.forEach((v) => {
res += v
})
}
const sum = ([a, b, c]) => {
return a + b + c
}
2、结合初始值
const course = ({teacher, leader, course = 'yeye'}) => {
// ...
}
course({
teacher: 'yy',
leader: '宵夜'
})
3、返回值
const getCourse = () => {
return {
teacher: '',
leader: ''
}
}
const { teacher, leader } = getCourse()