var a; //undefined
b; // b is not defined
var
存在变量提升,可重复声明同一变量,声明的变量均可改,函数作用域let
没有变量提升,不可重复声明同一变量,声明的变量均可改,块级作用域const
没有变量提升,不可重复声明同一变量,声明的基本数据类型不可改,引用类型可改属性,不可只声明变量而不赋值,块级作用域暂时性死区是指从当前作用域开始直到变量声明位置的这段代码区域。在这个区域内,如果你尝试访问变量,JavaScript引擎会抛出一个错误。这样设计的目的是为了帮助开发者避免在变量声明之前就使用变量,从而避免潜在的错误。
var a = 100;
if(1){
a = 10;
//在当前块作用域中存在a使用let/const声明的情况下,给a赋值10时,只会在当前作用域找变量a,
// 而这时,还未到声明时候,所以控制台Error:Cannot access 'a' before initialization
let a = 1;
}
方法 | 描述 |
---|---|
document.getElementById(id) | 通过id获取dom |
document.getElementsByTagName(tagName) | 通过标签名获取dom |
document.getElementsByClassName(class) | 通过class获取dom |
document.getElementsByName(name) | 通过标签的属性name获取dom |
document.querySelector(选择器) | 通过选择器获取dom |
document.querySelectorAll(选择器) | 通过选择器获取dom |
方法 | 描述 |
---|---|
createElement | 创建一个标签节点 |
createTextNode | 创建一个文本节点 |
cloneNode(deep) | 复制一个节点,连同属性与值都复制,deep为true时,连同后代节点一起复制,不传或者传false,则只复制当前节点 |
createDocumentFragment | 创建一个文档碎片节点 |
appendChild | 追加子元素 |
insertBefore | 将元素插入前面 |
removeChild | 删除子元素 |
replaceChild | 替换子元素 |
getAttribute | 获取节点的属性 |
createAttribute | 创建属性 |
setAttribute | 设置节点属性 |
romoveAttribute | 删除节点属性 |
element.attributes | 将属性生成类数组对象 |
元素节点 Node.ELEMENT_NODE(1)
属性节点 Node.ATTRIBUTE_NODE(2)
文本节点 Node.TEXT_NODE(3)
CDATA节点 Node.CDATA_SECTION_NODE(4)
实体引用名称节点 Node.ENTRY_REFERENCE_NODE(5)
实体名称节点 Node.ENTITY_NODE(6)
处理指令节点 Node.PROCESSING_INSTRUCTION_NODE(7)
注释节点 Node.COMMENT_NODE(8)
文档节点 Node.DOCUMENT_NODE(9)
文档类型节点 Node.DOCUMENT_TYPE_NODE(10)
文档片段节点 Node.DOCUMENT_FRAGMENT_NODE(11)
DTD声明节点 Node.NOTATION_NODE(12)
作用域指一个变量的作用的范围
在 JavaScript 中有两种作用域类型:
(1)全局作用域(<脚本>标签和.js文件就是所谓的作用域)
(2)局部作用域(局部作用域被分为函数作用域和块级作用域)
作用域链其实就是底层的变量查找机制。
在函数执行的时候,优先会查找当前作用域中的变量
如果当前作用域找不到则会依次逐级查找父级作用域直到全局作用域,所以子级作用域的变量可以访问到父级作用域的变量,但是反过来就不可以
方法 | 参数 |
---|---|
splice | splice(start, num, item1, item2, …) |
slice | slice(start, end) |
splice影响原数组,可以对原数组增删
slice不影响原数组,截取原数组返回截取后的数组
方法 | 参数 |
---|---|
substr | substr(start,length) |
substring | substring(start,end) |
indexOf()
方法返回数组中第一次出现给定元素的下标,如果不存在则返回 -1。
includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true
,否则返回 false
。
includes可以检测NaN
,indexOf不能检测NaN
,includes内部使用了Number.isNaN
对NaN
进行了匹配
for(var i = 0; i < 3; i++){
setTimeout(function(){
console.log(i);
},0);
};
答案:3,3,3
解决方法
for(let i = 0; i < 3; i++){
setTimeout(function(){
console.log(i);
},0);
};
// 0 1 2
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, 0)
})(i)
};
// 0 1 2
then
catch
all
race
是generator + Promise
的语法糖,主要的作用是用同步方式执行异步操作,await
只能在async函数
中使用,async函数
执行会返回一个Promise
,值由函数的return值所决定
https://mp.weixin.qq.com/s?__biz=Mzg2NjY2NTcyNg==&mid=2247483954&idx=1&sn=18489d9cbcd0562a017094058bc91610&chksm=ce4617a3f9319eb59a7e64703f87098382aa952f9d86f45b05c2ce47b0f248776276f453bdd4&scene=21#wechat_redirect
https://blog.csdn.net/weixin_50975172/article/details/130529339
分析一下new的整个过程:
简单实现一下new:
function myNew (fn, ...args) {
// 第一步:创建一个空对象
const obj = {}
// 第二步:继承构造函数的原型
obj.__proto__ = fn.prototype
// 第三步:this指向obj,并调用构造函数
fn.apply(obj, args)
// 第四步:返回对象
return obj
}
document.createDocumentFragment()
创建var oFragmeng = document.createDocumentFragment();
for(var i=0;i<10000;i++)
{
var op = document.createElement("span");
var oText = document.createTextNode(i);
op.appendChild(oText);
//先附加在文档碎片中
oFragmeng.appendChild(op);
}
//最后一次性添加到document中
document.body.appendChild(oFragmeng);
看不懂
宏任务(macro tasks)是一组独立的、顺序执行的任务。常见的宏任务包括:
微任务(micro tasks)是在宏任务执行过程中产生的任务,它的优先级高于宏任务。常见的微任务包括:
同步代码
直接执行异步代码
先放一边,并且将他回调函数
存起来,存的地方叫事件队列
同步代码
都执行完,再从事件队列
中把存起来的所有异步回调函数
拿出来按顺序执行console.log(1) // 同步
setTimeout(() => {
console.log(2) // 异步
}, 2000);
console.log(3) // 同步
setTimeout(() => {
console.log(4) // 异步
}, 0);
console.log(5) // 同步
输出: 1 3 5 4 2
value
:给target[key]设置初始值get
:调用target[key]时触发set
:设置target[key]时触发writable
:默认false,为true时此属性才能被赋值运算符修改enumerable
:默认false,为true时此属性才能被枚举configurable
:默认为false,为true时此属性的描述符才能被修改,才能被删除高阶函数:英文叫Higher-order function。JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
// 简单的高阶函数
function add(x, y, f) {
return f(x) + f(y);
}
//用代码验证一下:
add(-5, 6, Math.abs); // 11
像数组的map、reduce、filter
这些都是高阶函数
柯里化,英语:Currying(果然是满满的英译中的既视感),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
// 普通的add函数
function add(x, y) {
return x + y
}
// Currying后
function curryingAdd(x) {
return function (y) {
return x + y
}
}
add(1, 2) // 3
curryingAdd(1)(2) // 3
好处
参数复用
延迟执行
const add1 = (x) => x + 1;
const mul3 = (x) => x * 3;
const div2 = (x) => x / 2;
div2(mul3(add1(add1(0)))); //=>3
而这样的写法可读性明显太差了,我们可以构建一个compose函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后compose返回的也是一个函数,达到以下的效果:
const operate = compose(div2, mul3, add1, add1)
operate(0) //=>相当于div2(mul3(add1(add1(0))))
operate(2) //=>相当于div2(mul3(add1(add1(2))))
看不懂
CommonJS 是同步加载模块,ES6是异步加载模块
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块
输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值
CommonJS 是同步加载模块,ES6是异步加载模块
https://mp.weixin.qq.com/s?__biz=Mzg2NjY2NTcyNg==&mid=2247484979&idx=1&sn=ff9fd50664a1f75a770f7e396c72fd2e&chksm=ce4613a2f9319ab4fb841798cc2fb2d17719545645a592b88f276731a3426773b3f86ee4aade&scene=21#wechat_redirect
// 第一种
const a = {
i: 0,
toString() {
return ++this.i
}
}
console.log(a == 1 && a == 2 && a == 3) // true
// 第二种
const a = [1, 2, 3]
a.join = a.shift
console.log(a == 1 && a == 2 && a == 3) // true
// 第三种
let i = 0
Object.defineProperty(global, 'a', {
get() {
return ++i
}
})
console.log(a == 1 && a == 2 && a == 3) // true
length
是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数
看不懂
对于算法来说 无非就是时间换空间 空间换时间
还没复习到
forEach()
方法是一个迭代方法。它按索引升序地为数组中的每个元素调用一次提供的 callbackFn
函数。与 map()
不同,forEach()
总是返回 undefined
,而且不能继续链式调用。其典型的用法是在链式调用的末尾执行某些操作。
除非抛出异常,否则没有办法停止或中断 forEach()
循环。如果有这样的需求,则不应该使用 forEach()
方法。
location.href
:window.location.href =“https://www.onlineinterviewquestions.com/”)location.replace
:window.location.replace(" https://www.onlineinterviewquestions.com/;")事件 | 说明 |
---|---|
click | 单机鼠标左键触发 |
dbclick | 双击鼠标左键触发 |
mousedown | 单机鼠标任意一个按键都触发 |
mouseout | 鼠标指针位于某个元素上且将要移出元素边界时触发 |
mouseover | 鼠标指针出某个元素到另一个元素上时触发 |
mouseup | 松开任意鼠标按键时触发 |
mousemove | 鼠标在某个元素上时持续发生 |
mouseenter | 鼠标进入某个元素边界时触发 |
mouseleave | 鼠标离开某个元素边界时触发 |
注明:event
对象上的keyCode
属性,是按下的按键的ASCLL值
,通过这个值可辨别是按下哪个按键。ASCLL
表在此ASCII码一览表,ASCII码对照表
事件 | 说明 |
---|---|
onkeydown | 某个键盘按键被按下时触发 |
onkeyup | 某个键盘按键被松开时触发 |
onkeypress | 某个按键被按下时触发,不监听功能键,如ctrl,shift |
属性 | 说明 | 兼容性 |
---|---|---|
offsetX | 以当前的目标元素左上角为原点,定位x轴坐标 | 除Mozilla外都兼容 |
offsetY | 以当前的目标元素左上角为原点,定位y轴坐标 | 除Mozilla外都兼容 |
clientX | 以浏览器可视窗口左上角为原点,定位x轴坐标 | 都兼容 |
clientY | 以浏览器可视窗口左上角为原点,定位y轴坐标 | 都兼容 |
pageX | 以doument对象左上角为原点,定位x轴坐标 | 除IE外都兼容 |
pageY | 以doument对象左上角为原点,定位y轴坐标 | 除IE外都兼容 |
screenX | 以计算机屏幕左上顶角为原点,定位x轴坐标(多屏幕会影响) | 全兼容 |
screenY | 以计算机屏幕左上顶角为原点,定位y轴坐标 | 全兼容 |
layerX | 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 x 轴坐标 | Mozilla 和 Safari |
layerY | 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 y 轴坐标 | Mozilla 和 Safari |
属性 | 说明 |
---|---|
offsetLeft | 获取当前元素到定位父节点的left方向的距离 |
offsetTop | 获取当前元素到定位父节点的top方向的距离 |
offsetWidth | 获取当前元素 width + 左右padding + 左右border-width |
offsetHeight | 获取当前元素 height + 上下padding + 上下border-width |
clientWidth | 获取当前元素 width + 左右padding |
clientHeight | 获取当前元素 height + 上下padding |
scrollWidth | 当前元素内容真实的宽度,内容不超出盒子宽度时为盒子的clientWidth |
scrollHeight | 当前元素内容真实的高度,内容不超出盒子高度时为盒子的clientHeight |
属性 | 说明 |
---|---|
innerWidth | innerWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏) |
innerHeight | innerWidth 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏) |
属性 | 说明 |
---|---|
document.documentElement.clientWidth | 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏、滚动条) |
document.documentElement.clientHeight | 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏、滚动条) |
document.documentElement.offsetHeight | 获取整个文档的高度(包含body的margin) |
document.body.offsetHeight | 获取整个文档的高度(不包含body的margin) |
document.documentElement.scrollTop | 返回文档的滚动top方向的距离(当窗口发生滚动时值改变) |
document.documentElement.scrollLeft | 返回文档的滚动left方向的距离(当窗口发生滚动时值改变) |
我们可以总结出:
e.target
:触发事件的元素e.currentTarget
:绑定事件的元素function fn1 () {
console.log(arguments)
}
fn1(1, 2, 3)
// [Arguments] { '0': 1, '1': 2, '2': 3 }
const fn2 = () => {
console.log(arguments)
}
fn2(1, 2, 3)
// arguments is not defined
其实就是这样
[1,2,3].map((item,index)=>{
parseInt(item,index)
})
parseInt的第二个参数是从2开始的
- parseInt('1', 0) 0 被当成10机制计算 所以返回1
- parseInt('2', 1) 第二个参数从2开始
- parseInt('3', 2) 2 当成2机制
所以结果为[1,NaN,NaN]