JavaScript深入理解(14课)笔记-ES6知识点详细解析

14.ES6知识点详细解析

00:22:00
const names = ["abc","cba","nba"]
for (const i = 0; i < names.length; i++) {
    console.log(names[i])
}

分解上面的代码块为:
{
    const i = 0
    console.log(names[i])
}
{
    const i = 上面的 i++ 后赋值到这边;是因为常量 i 不能进行++ 操作,【所以会报错!】
    console.log(names[i])
}

用 for … of 方式遍历数组(对象),下面这样是可以的
for (const item of names) {
    console.log(item)
}

00:27:00
在ES6中,我们还有一个概念称之为暂时性死区:
· 它表达的意思是在一个代码中,使用let、const声明的变量,在声明之前,变量都是不可以访问的;
· 我们将这种现象称之为temporal dead zone (暂时性死区,TDZ);

var foo = "foo"
if (true) {
    console.log(foo)  //报错【社区叫法“暂时性死区”】(当然,如果下一行不写,不会报错)
    let foo = "abc"
}


var、let、const的选择
那么在开发中,我们到底应该选择使用哪一种方式来定义我们的变量呢?

对于var的使用:
· 我们需要明白一个事实,var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些历史遗留问题;
· 其实是JavaScript在设计之初的一种语言缺陷;
· 当然目前市场上也在利用这种缺陷出一系列的面试题,来考察大家对JavaScript语言本身以及底层的理解;
· 但是在实际工作中,我们可以使用最新的规范来编写,也就是不再使用var来定义变量了;
  【因为:构建工具的基础上创建项目\开发项目   webpack/vite/rollup    babel => ES6 -> ES5】

对于let、const:
· 对于let和const来说,是目前开发中推荐使用的;
· 我们会优先推荐使用const,这样可以保证数据的安全性不会被随意的篡改;
· 只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let;
· 这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范;

ES6的其他知识点:
// ES6之前拼接字符串和其他标识符
const name ="why"
const age = 18
const height=1.88
console.log("my name is" + name + ", age is " + age + ", height is " + height)

// ES6提供模板字符串 `` 【键盘Tab 上方】
const message = `my name is ${name}, age is ${age}, height is ${height}`
console.log(message)

const info = `age double is ${age * 2}`
console.log(info)

function doubleAge() {
    return age *2
}
const info2 = `double age is ${doubleAge()}`
console.log(info2)

00:48:00
function foo(m, n, x) {
    console.log(m, n, x, '---------')
}

//另外调用函数的方式:标签模块字符串
//foo``
//foo`Hello World`

const name = "why"
const age = 18

foo`Hello${name}Wo${age}rld`
输出:['Hello', 'Wo', 'rld'] 'why' 18 '---------'

说明:
// 第一个参数依然是模块字符串中整个字符串,只是被切成多块,放到了一个数组中
// 第二个参数是模块字符串中,第一个${}


题外话:
react开发【框架代码中就有运用到“标签模板字符串”】
all in js: html css js in js 即:在js中去编写:html, css, js
css in js第三方库
styled-components

Vue开发
template 即:html形式
script
style

// ES5以及之前给参数默认值
/*
缺点:
1. 写起来很麻烦,并且代码的阅读性是比较差
2. 这种写法是有bug
*/
function foo(m, n) {
    m = m || "aaa"
    n = n || "bbb"

    console.log(m, n)
}
foo()
foo(0, "")

//ES5要写这样才没有bug
function foo() {
    var m = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "aaa";
    var n = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "bbb";

    console.log(m, n)
}

// 1.ES6可以给函数参数提供默认值
function foo(m = "aaa", n = "bbb") {
    console.log(m, n)

// 2.对象参数和默认值以及解构
function printInfo({name, age} = {name: "why", age: 18}) {
    console.log(name,age)
}

printInfo()  // why 18
printInfo({name: "kobe", age: 40})  // kobe 40

//上面“对象参数和默认值”的另一种写法:
function printInfo({name = "why",age = 18} = {}) {
    console.log(name, age)
}

// 3.有默认值的形参最好放到最后
function bar(x, y, z=30) {
    console.log(x, y, z)
}

// 4.有默认值的函数的length属性
function baz(x, y, z = 30, m, n) {
    console.log(x, y, z, m, n)
}
console.log(baz.length) //2 ,默认值前面有几个参数,则长度为几个

ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
· 如果最后一个参数是“...”为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;

那么剩余参数和arguments有什么区别呢?
· 剩余参数只包含那些没有对应形参的实参,而arguments对象包含了传给函数的所有实参;
· arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;
· arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供并且希望以此来替代arguments的;

// 函数的剩余参数
function foo(m, n, ...args) {
    console.log(m, n)  //20 30
    console.log(args)  //[40, 50, 60]

    console.log(arguments)  //[20, 30, 40, 50, 60, callee: (...), Symbol(Symbol.iterator): ƒ]
}
foo(20, 30, 40, 50, 60)


// rest paramaters【...args】必须放到最后
// 不然会报错:Rest parameter must be last formal parameter


题外话:
//下面这样写可以,但不推荐
function foo(m, n=m+1) {
    console.log(m, n)
}
foo(10);
//------------------------

var bar = () => {
    console.log(this, arguments)
}
console.log(bar.prototype)  //undefined
const b = new bar()  //报错:bar is not a constructor

箭头函数没有显式原型
箭头函数没有this 和 arguments,上面代码会去父级作用域查找 this 和 arguments
箭头函数不能new操作

展开语法(Spread syntax) :
· 可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开;
· 还可以在构造字面量对象时,将对象表达式按key-value的方式展开;

const names = ["abc", "cba", "nba"]
const name = "why"
//1.函数调用时
function foo(x, y, z) {
    console.log(x,y,z)
}
// foo.apply(null, names)
foo(...names)
foo(...name)

//2.构造数组时
const newNames = [...names, ...name]
console.log(newNames)


//3.ES2018(ES9)
const info = {name: "why", age: 18}
const obj = {...info, address:"广州市"}
console.log(obj)

//4.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: "广州市", ...names }
console.log(obj)


01:51:00
展开语法 实际做的是浅拷贝

const info = {
    name: "why",
    friend: { name: "kobe" }
}
const obj = { ...info, name: "coderwhy" } //展开后,又把 name属性值覆盖了
// console. log (obj)
obj.friend.name = "james"
console.log(info.friend.name)  //james
【浅拷贝,这边改变 obj.friend对象的name属性值,info对象里的也相应改变了】

ES6中表示数值的方式:
const num1 =100 //十进制
const num2 =0b100 //二进制 binary
const num3 =0o100 //八进制 octonary
const num4 =0x100 // 十六进制 hexadecimal

console.log(num1, num2, num3, num4) //100 4 64 256

//大的数值的连接符(ES2021-ES12)
const num = 10_000_000_000_000_000
console.log(num) //10000000000000000

// 1.ES6之前,对象的属性名(key)
var obj = {
    name: "why",
    friend: { name: "kobe" },
    age:18
}
obj['newName']= "james"
console.log(obj)

// 2.ES6中Symbol的基本使用
const s1 = Symbol()
const s2 = Symbol()
console.log(s1===s2)  //false

// ES2019(ES10)中,Symbol还有一个描述(description)
const s3 = Symbol("aaa")
console.log(s3.description)

// 3.Symbol值作为key
// 3.1.在定义对象字面量时使用
const obj = {
    [s1]:"abc",
    [s2]:"cba"
}
// 3.2.新增属性
obj[s3] = "nba"

// 3.3.0bject.defineProperty方式
const s4 = Symbol()
Object.defineProperty(obj, s4, {
    enumerable: true,
    configurable: true,
    writable: true,
    value: "mba"
})

console.log(obj[s1], obj[s2], obj[s3], obj[s4]) //abc cba nba mba
//·注意:不能通过 . 语法获取
console.log(obj.s1) //undefined

// 4.使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值
// 需要Object.getOwnPropertySymbols来获取所有Symbol的key
console.log(Object.keys(obj)) //[]  获取到空数组
console.log(Object.getOwnPropertyNames(obj)) //[]
console.log(Object.getOwnPropertySymbols(obj)) //这种可以获取到所有Symbols键数组

const sKeys = Object.getOwnPropertySymbols(obj)
for (const skey of sKeys) {
    console.log(obj[sKey])
}

// 5.Symbol.for(key)/Symbol.keyFor(symbol) 创建相同的键
const sa = Symbol.for("aaa")
const sb = Symbol.for("aaa")
console.log(sa === sb) //true

const key =Symbol.keyFor(sa)
console.log(key)
const sc = Symbol.for(key)
console.log(sa === sc) //true

Symbol的基本使用

Symbol是什么呢?Symbol是ES6中新增的一个基本数据类型,翻译为符号。
那么为什么需要Symbol呢?
· 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突;
· 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖掉它内部的某个属性;
· 比如我们前面在讲apply、call、bind实现时,我们有给其中添加一个fn属性,那么如果它内部原来已经有了fn属性了
呢?
· 比如开发中我们使用混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉;

Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
· Symbol值是通过Symbol函数来生成的,生成后可以作为属性名;
· 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值;

Symbol即使多次创建值,它们也是不同的:Symbol函数执行后每次创建出来的值都是独一无二的;
我们也可以在创建Symbol值的时候传入一个描述description:这个是ES2019(ES10)新增的特性;


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值