js知识

160 阅读5分钟

var,let,const

var

  • 声明只区分全局或者函数作用域里
  • 全局声明时(在最顶部的范围)创建window对象的属性
  • 可重复声明(在同一个作用域里)
  • 会声明提升,在赋值前访问返回undefined

let

  • let和const声明在块作用域{}里,for(let a of [])属于块作用域
  • 全局声明时,不会创建window对象的属性
  • 不可重复声明(在同一个作用域里)

1.switch不同的case里声明属于不同的作用域

  • 不会声明提升,在赋值前访问会ReferenceError,该变量处在一个当前块顶部到初始化处理的“暂存死区”中

const

  • 不能重新赋值
  • 必须在声明的同一语句中指定它的值,否则SyntaxError
  • 声明其实创建的是一个值的只读引用

所以可以声明为object,可以改变object的key或者value或者数组的单元,但是不能整个赋值一个新的对象或者数组

this

文档

developer.mozilla.org/zhCN/docs/W…

普通函数this运行时绑定

//
fn(1,2)				// fn.call(undefined,1,2)
obj.fn(1,2)			// obj.fn.call(obj,1,2)
arr[0](1,2)			// arr[0].call(arr,1,2)

箭头函数

//箭头函数this永远指向定义时的词法作用域,不会通过call,apply,bind改变
()=>{return this}

bind(this)

//如果通过bind生成了一个指定this的函数,其this永远绑定在第一次绑定的this上
let fn2=fn.bind(this1)
fn2.bind(this2)

构造函数

//构造函数与普通函数this差不多,在调用成员对象时候决定this指向调用者obj
function ClassObj(name){
	this.name=name
  	//当new一个函数的时候,return this绑定到构建的对象上
    //return this
}
var obj=new ClassObj('张三')
obj.name// 张三

原型链上的this

var o = {
  f: function() { 
    return this.a + this.b; 
  }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
//如果在一个对象上的原型上找到,this还是指向这个对象

Promise

then

调用 Promise 的 then(..) 会自动创建一个的 Promise 从调用返回

catch

promise.then(null,function(err){})

等价于 promise.catch(function(err){})

Promise.resolve

Promise.resolve(fn)如果fn是一个promise那么返回fn,两者是相等的,如果是其他函数,会转成一个带有fn返回值的promise

Promise.all

Promise.all([])

如果都fulfilled返回一个数组,包含所有同步或异步的值;如果有一个失败(rejected),则返回失败,失败的原因是第一个失败 promise 的结果。

[[PromiseStatus]]: "rejected"
[[PromiseValue]]: 2

如果是空数组,将直接完成

Promise.allSettled

Promise.allSettled([])

如果都已经fulfilled或者rejected返回[]包含所有同步或异步的状态和值。

[[PromiseStatus]]: "fulfilled"
[[PromiseValue]]: Array(2)
0: {status: "fulfilled", value: 1}
1: {status: "rejected", value: 2}

如果是空数组,将直接完成

Promise.race

Promise.race([])只要有其中一个promise完成或者拒绝,就返回那个promise的值多个promise竞速

如果是空数组,那么将一直是pending

[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined

setTimeout(fn,time)

只是在一定时间time后将fn放入事件队列中,所以不能保证在time时间点执行fn,可能在这个时间点之后,但一定不在这个时间之前

==与===

==会进行强制类型转换,===不进行强制类型转换,所以如果能保证两边的类型是一样的,==也是安全效率的

generator与yield

文档

developer.mozilla.org/zh-CN/docs/…*

function* foo(x) {
var y = x * (yield);
return y;
}
var it = foo( 6 );
// 启动foo(..)
it.next();
var res = it.next( 7 );
res.value; // 42

!!!第一个 next(..) 总是启动一个生成器,并运行到第一个 yield 处。不过,是第二个 next(..) 调用完成第一个被暂停的 yield 表达式,第三个 next(..) 调用完成第二个 yield,以此类推

Array

Array.from

生成0-10的数组 Array.from({length: 11},(item,i => i))

Array.prototype.every

[].every(()=>{})		// true

every 和数学中的"所有"类似,当所有的元素都符合条件才会返回true。正因如此,若传入一个空数组,无论如何都会返回 true。(这种情况属于无条件正确:正因为一个空集合没有元素,所以它其中的所有元素都符合给定的条件。)

indexOf和includes区别

  • indexOf不能匹配NaN这个值,includes可以
  • indexOf()includes()无参调用时,将匹配数组中的undefined

Array.prototype.{flat,flatMap}

let r;
r = ["1", ["8", ["9", ["1"]]]].flat();//4维数组,默认降维1,变成3维数组
console.log(r); //>> [ '1', '8', [ '9', ['1'] ] ]

r = ["1", ["8", ["9", ["1"]]]].flat(2); //4维数组,降维2,变成2维数组
console.log(r); //>> [ '1', '8', '9', ['1'] ]

r = ["1", ["8", ["9", ["1"]]]].flat(Infinity);//4维数组,最多变成1维数组
console.log(r); //>> [ '1', '8', '9', '1' ]

接着来看看flatMap()

let r;
r = ["I love", "coffe 1891"].map(item => item.split(" "));
console.log(r); //>> [ [ 'I', 'love' ], [ 'coffe', '1891' ] ]

r = ["I love", "coffe 1891"].flatMap(item => item.split(" "));
console.log(r); //>>[ 'I', 'love', 'coffe', '1891' ]

正则表达式

正则表达式命名捕获组

const reDate = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
  match = reDate.exec("2018-08-06");
console.log(match);
//>> [2018-08-06, 08, 06, 2018, groups: {day: 06, month: 08, year: 2018}]

//此时用groups对象来获取年月日,无论正则表达式怎么变换,这下面三行不用改了,省事!
let year = match.groups.year; //>> 2018
let month = match.groups.month; //>> 08
let day = match.groups.day; //>> 06

可以提取指定结构中的内容

数据结构互转

arrayArray.from()

setnew Set()

map new Map()

objectObject.fromEntries()

for...in 和for...of

for...in不仅会遍历原型链上的属性,而且会遍历出其所有可枚举属性

for...of不会遍历原型链的属性,而且对于可迭代对象[Symbol(Symbol.iterator)](数组、类数组、Set、Map)不会遍历出额外的属性