let
1、let定义变量的方式
// 1、 错误的方式
console.log(a)
let a = 1
2、 let定义的变量所在的范围会形成作用域
if (true) {
// var定义的变量在它所在的范围没有形成作用域
// var a = 1
// var定义的变量在它所在的范围形成作用域
let a = 1
}
console.log(a)
3、
let arr = [1, 2, 3, 4, 5]
for (let i = 0; i < arr.length; i++) {
console.log(i)
}
let arr = []
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i)
}
}
arr[0]()
arr[1]()
arr[2]()
4、let定义的变量的值是可以修改的
let a = 1
a = 2
console.log(a);
const
使用const声明的变量不能修改
const myName = 'zs'
myName = 'ls'
注意:使用const声明变量的同时需要初始化
const myName = '';
使用const声明的变量如果指是对象,那么修改对象中的属性的值是允许的
const myObj = {
age:18
}
myObj.age = 20
不能重新指向新的对象
myObj = {
age:18
}
数组解构:简化对数组元素提取的操作
1、根据数组下标获取数据
const arr = [100, 200, 300]
const foo = arr[0]
const bar = arr[1]
const baz = arr[2]
2、基本的解构方式
const [foo,bar,baz] = arr
console.log(foo,bar,baz)
3、提取数组中的最后一个元素
// const [,,baz] = arr
// console.log(baz);
4、剩余运算符 ...
需求:第一个元素单独提取,剩下的元素打包提取
注意:剩余运算符声明的变量只能放在最后!!!!
const [foo,...rest] = arr
console.log(foo);
console.log(rest);
5、
const [foo] =arr
console.log(foo);
6、默认解构
const [foo,bar,baz=456,more=123] = arr
console.log(more,baz);
需求:获取一个路径字符串中的最后一个目录,输出baz
// 1、按照指定的字符切割字符串得到数组
// 2、解构数组
// 3、输出结果
const path = "foo/bar/baz"
var arr = path.split('/')
const [, , baz] = arr
console.log(arr)
对象解构
const obj = {
myName: 'zs',
age: 18,
getAge: function() {
return this.age
}
}
1、 对象解构基本方式
const {
myName: myNameVal
} = obj
console.log(myNameVal);
2、 解构默认值
const {
myName: myNameVal = 'jack'
} = obj
console.log(myNameVal);
3、
const {
getAge: getAgeFunc
} = obj
const age = getAgeFunc()
console.log(age);
const {
getAge
} = obj
const age = getAge()
console.log(age);
模板字符串
1、 普通字符串
const str = "学习es6,很强大"
const str = "学习es6,\n很强大"
2、 模版字符串
// 允许换行
const str = `学习es6,
很强大`
const str = `学习es6,很强大`
//可以使用插值表达式, 重点掌握!!! $ {}
let lang = 'javascript'
const str = `学习${lang},很强大,${1+1+1},${Math.random()},${lang?1:0}`
模版字符串标签函数
const str = console.log`hello javascript`
function myTagFunc(strings,myName,gender){
console.log(strings)
console.log(myName);
console.log(gender);
const sex = gender==='female' ? '女' :'男'
const newStr = strings[0] + myName + strings[1] + sex + strings[2]
return newStr
}
模版字符串标签函数
const myName = "zs"
const gender = "female"
const str = myTagFunc`hi,${myName} is a ${gender}`
console.log(str);
操作字符串的扩展方法
startsWith\endsWith\includes
const str = 'Error: foo is not defined.'
需求:判断str是否以Error开头
console.log(str.startsWith("Error"))
需求:判断str是否以.结尾
console.log(str.endsWith('.'))
需求:判断str是否包含foo
console.log(str.includes("foo1"))
函数参数默认值
注意:含默认的参数,只能放在最后
function foo(bar,enable=""){
console.log(bar);
console.log(enable);
// 第一种防止函数内部出错的方式,也叫增强代码健壮性
let str
if(enable){
// 把字符串全部转成大写
str = enable.toUpperCase()
}
// 第二种方式,给函数参数提供默认值
const str = enable.toUpperCase()
console.log(str)
console.log('foo函数执行了')
}
// foo("bar","enable")
foo("bar")
函数剩余参数
注意:剩余参数智能放在参数列表的最后一个位置
function fun(n,...args){
console.log(n)
console.log(args)
}
fun(1,2,3,4,5)
fun(1,2,3)
fun(2,3,4,5,6,9,0)
展开/延展操作符
// 展开数组
const arr = ['foo', 'bar', 'baz']
console.log.apply(console, arr)
// 展开的数据
console.log(...arr)
const newArr = [...arr]
console.log(newArr)
箭头函数
函数的基本定义方式
function plus(a) {
return a + 1
}
基本定义方式
const plus = (a) => {
console.log(this)
return a + 1
}
const res = plus(1)
console.log(res)
// 注意:
// 1、 箭头函数中没有this
plus(1)
// 2、 箭头函数简写
// 2.1、 只有一个参数的时候才能省略括号
const plus = a => {
return a + 1
}
const plus = (a, b) => {
return a + b
}
// 2.2、 函数体中的代码之后一行的时候, 可以吧 {} 和return去掉
const plus = a => a + 1
const plus = a => {
console.log('plus invoke')
return a + 1
}
console.log(plus(1));
案例:
// 1、 箭头函数中更没有this
setTimeout(() => {
console.log(this)
console.log(1)
}, 1000)
const person = {
myName: 'javascript',
getMyName: function() {
console.log(this)
setTimeout(() => {
console.log(`hi,myName is ${this.myName}`)
}, 1000)
}
}
person.getMyName()
// 2、作为回调函数,在异步编程中使用
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
需求:过滤出数值中的偶数
1、判断偶数是 对2取余 %
arr.filter(function(item) {
let res
if (item % 2 === 0) {
res = item
}
return res
})
2、案例用箭头函数简写
const newArr = arr.filter(item => item % 2 === 0)
console.log(newArr)
对象字面量增强
对象中属性与方法的简洁表示法
1.对象字面量是什么?创建对象的一种方式
const person={ name:‘zhangsan’, age:34 }
2.属性的简洁表达式==>键名和变量或常量名一样的时候,可以只写一个
const age=23;
const person={ name:‘zhangsan’, // age:age, //这里可以简写 age }
console.log(person)
3.方法的简洁表示法==>方法可以省略冒号和function 关键字
const person={
// speak:function(){
} speak(){
console.log(‘这是方法的简写形式’)
}
}
person.speak();//方法的调用
对象中[]方括号语法
1.方括号语法的用法
const prop=‘age’;
const person={}; //之前的写法
person[prop]=23;//将age属性添加到了person对象中
console.log(person)//{age:23}
2.增强以后:方括号语法可以写到对象字面量中
const prop=‘age’;
const person={
[prop]:12//prop为一个变量
}
console.log(person);//{age:23}
3.方括号中可以放什么
${} 模板字符串
[值或通过计算可以得到值得(表达式)]
const attr=‘age’;
const func=()=>‘age2’;
const people={
[prop]:23,//[] 里面可以是常量
[func()]:45,//[] 可以是一个计算的结果
[‘sex’+‘3’]:34//[]里面也可以是 字符串拼接
}
console.log(people);
4.方括号语法和点语法的区别
点语法是方括号语法的特殊形式, 当我们的属性名为合法标识符的时候 可以使用点语法,特殊的属性名 需要使用方括号语法。
对象赋值 Object.assign()
面试题or笔试题:描述深浅拷贝,举例子说明
1.浅拷贝和深拷贝都能创建出一个新的对象,
但浅拷贝在复制引用类型时,只复制引用地址,新旧对象还是共享同一块内存,修改对象属性会影响原对象;
而深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
2.浅拷贝常见方法
Object.assign()
扩展运算符
Array.concat()
Array.slice()
3.深拷贝常见方法
_.cloneDeep()
JSON.stringify()
手写递归方法
案例
const source1 = {
a: 123,
b: 123
}
const source2 = {
b: 678,
d: 789
}
const target = {
a: 456,
c: 789
}
过程
const source1 = {
a: 123,
b: 678,
d: 789
}
const target = {
c: 789,
a: 123,
b: 678,
d: 789
}
1、过程
2、函数最终的值是存放target,并且会返回target对象
3、浅拷贝 newObj和target是同一个对象
const newObj = Object.assign(target, source1, source2)
console.log(newObj);
console.log(newObj === target)
// 深拷贝、 浅拷贝
const obj = {
myName: 'zs',
age: 18
}
浅拷贝
const newObj = obj
newObj.myName = 'lis'
console.log(obj);
console.log(newObj);
// 复制对象, 修改新对象的值, 不影响就对象的值
const newObj = Object.assign({}, obj)
newObj.myName = 'aaa'
console.log(obj);
// 注意:!!!!!!!
// 生成一个新的对象
function fun(obj) {
// todo
console.log(obj)
obj.myName = 'lisi'
return obj
}
const oldObj = {
myName: 'zs'
}
const newObj = fun(oldObj)
console.log(newObj);
console.log(oldObj);
应用:简化对象参数接收
function Block(options) {
console.log(this)
// this.width = options.width
// this.height = options.height
// this.x = options.x
// this.y = options.y
this.z = 10
return Object.assign(this, options)
}
const block1 = new Block({
width: 100,
height: 200,
x: 50,
y: 50
})
console.log(block1)
判断值是否相等
console.log(0 === false)
console.log(+0 === -0)
console.log(NaN === NaN)
console.log('-------------------------')
// object.is
console.log(Object.is(+0, -0));
console.log(Object.is(NaN, NaN));
class关键字定义类
原来定义类的方式
function Person(name, age) {
this.myName = name
this.age = age
}
Person.prototype.sayHi = function() {
console.log(`hi,myName is ${myName}`)
}
const p1 = new Person("zs", 18)
p1.sayHi()
class关键字定义类
class Person {
constructor(name, age) {
this.myName = name
this.age = age
}
sayHi = function() {
console.log(`hi,myName is ${this.myName}`)
}
// 静态成员/方法
static create(name, age) {
const p = new Person(name, age)
return p
}
}
// const p1 = new Person("zs",18)
// p1.sayHi()
const p1 = Person.create("lisi", 25)
p1.sayHi()
extends
继承
class Person{
constructor(name,age) {
this.myName = name
this.age = age
}
sayHi = function (){
console.log('sayHi()')
}
}
class Student extends Person{
constructor(name,age,number) {
super(name,age) // super可以理解为父类构造函数
this.number = number
}
}
const s1 = new Student("tom",20,101010)
console.log(s1);
set
Set数据结构
const s = new Set()
1、 添加数据
const res = s.add(1)
console.log(res)
链式调用
s.add(1).add(2).add(3).add(4).add(5)
console.log(s)
2、 获取数据
2.1、 forEach()
s.forEach(i => console.log(i))
2.2、for..of
for (let i of s) {
console.log(i)
}
3、 获取Set中存储的数据的个数
console.log(s.size)
4、 判断指定的数是否在Set数据结构中
console.log(s.has(3))
5、 删除指定的数据
console.log(s.delete(5)); // s.delete()返回值表示删除是否成功
6、 清空Set数据
s.clear()
console.log(s);
7、 特性: Set中保存的数据是不能重复的。 如果给他重复的数据, Set会自动把重复的数据给删除
需求: 把一个数组中的重复的元素给删除(数组去重)
const arr = [1, 3, 4, 6, 2, 4, 7, 5, 8]
const s = new Set(arr)
const newArr = Array.from(s)
console.log(newArr);
// 简化
const newArr = Array.from(new Set(arr))
// 简化: 使用延展操作符
const newArr = [...new Set(arr)]
console.log(newArr);
map
Map数据结构
const map = new Map()
新增数据
map.set("myName","zs")
获取数据
console.log(map.get("myName"));
根据key判断是否存在
console.log(map.has("myName"));
删除
delete()
清空
clear()
key使用变量的方式来进行增、删除、清空
遍历map中的数据
map.forEach((value,key)=>{
console.log(value,key)
})
_for_of...
for...of 遍历获取数据
1、遍历数组
const arr = [100, 200, 300]
for (let item of arr) {
console.log(item)
}
2、遍历Set
3、遍历Map
const m = new Map()
m.set('foo', 1)
m.set('bar', 2)
for (let [key, value] of m) {
console.log(key + ":" + value)
}
4、注意:for...of 不能遍历对象
const obj = {
myName: 'sz',
age: 18
}
for (let item of obj) {
console.log(item)
}
5、
-
Object.keys() 获取对象中的所有的key
-
Object.values() 获取对象中的所有的value
-
Object.entries() 获取对象中的所有键值对
const obj = { myName: 'ZS', age: 18 } const res = Object.keys(obj) console.log(res); const res = Object.values(obj) console.log(res) const res = Object.entries(obj) console.log(res) for (let key of Object.keys(obj)) { console.log(key) } // 遍历对象中的所有值 // 遍历对象中的所有的键值对,并输出
es7新特性
es2016新内容
const arr = [1, true, NaN, 23, "hello"]
indexOf 判断某个元素是否在数组中,返回这个元素在数组中的索引;如果元素不在数组中,返回-1
console.log(arr.indexOf(true));
console.log(arr.indexOf(null));
console.log(arr.indexOf(NaN)); // 陷阱 -1
includes 判断数组是否包含指定的元素
console.log(arr.includes(1));
console.log(arr.includes(NaN)); //true
指数运算符 **
-
需求:计算2的3次方
console.log(Math.pow(2, 3)); console.log(2 ** 3);