let、const、var的使用区别
1.var定义变量,没有块的概念,可以跨块访问,不能跨函数访问,不初始化出现undefined,不会报错。
2.let定义变量,只能在块作用域里访问,也不能跨函数访问,对函数外部无影响。
3.const定义常量,只能在块作用域里访问,也不能跨函数访问,使用时必须初始化(即必须赋值),而且不能修改。
变量提升和函数提升
- 变量声明的提升是以变量所处的第一层词法作用域为“单位”的,即全局作用域中声明的变量会提升至全局最顶层,函数内声明的变量只会提升至该函数作用域最顶层
- 函数提升只会提升函数声明,而不会提升函数表达式
- 函数提升优先于变量提升
Map与普通对象的区别
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象
输入一个网址,直到网址打开并加载结束,这个过程浏览器发生了什么
查看浏览器中是否有缓存,有的话直接访问缓存
如果缓存过期或者没有缓存,重新请求
在发送http请求前,需要域名解析,获取相应的IP地址
浏览器想服务器发起tcp链接,与浏览器建立tcp三次握手
握手成功后,浏览器向服务器发送http请求,请求数据包
服务器处理收到的请求,将数据返回至浏览器
浏览器收到HTTP响应
读取页面内容,浏览器渲染,解析html源码
rem是根据根的font-size变化,而em是根据父级的font-size变化
基本数据类型:number,string,null,undefined,boolean,symbol,bigInt
引用数据类型: object
call,apply,bind的作用区别
作用:用来改变函数this指向
相同处:第一个参数都是this要指向的对象
区别一:call()和apply()都是对函数的直接地调用,而bind()本身返回一个函数,后面还需要()进行调用
区别二:call()和bind()传参可以一个一个传入,但是apply()要以数组格式传参
bind 函数
Function.prototype.bind = function() {
var self = this;
var context = Array.prototype.shift.call(arguments)
var args = Array.prorotype.slice.call(arguments)
return function() {
self.apply(context, Array.prototype.concat.call(args, Array.prorotype.slice.call(arguments)))
}
}
js调用机制
- JavaScript的单线程
- 任务队列
- 同步任务
- 异步任务
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
具体运行机制可以理解为,当主线程的异步函数在被调用的时候,会请求工作线程的帮助。工作线程接收这个任务并执行。主线程可以继续运行后面的函数,而不必阻塞在这。
浏览器线程
- 主进程
- gpu进程
- 第三方插件进程
- 渲染进程
- gui线程
如果修改了一些元素的颜色或者背景色,页面就会重绘(Repaint),如果修改元素的尺寸,页面就会回流(Reflow),当页面需要Repaing和Reflow时GUI多会执行,进行页面绘制。 - js引擎线程:
js引擎线程就是js内核,负责解析与执行js代码,也称为主线程。浏览器同时只能有一个JS引擎线程在运行JS程序,所以js是单线程运行的。 - 事件循环线程
管理着一个事件队列(task queue),当js执行碰到事件绑定和一些异步操作时,会把对应的事件添加到对应的线程中(比如定时器操作,便把定时器事件添加到定时器线程),等异步事件有了结果,便把他们的回调操作添加到事件队列,等待js引擎线程空闲时来处理。 - 定时器线程
由于js是单线程运行,所以不能抽出时间来计时,只能另开辟一个线程来处理定时器任务,等计时完成,把定时器要执行的操作添加到事件任务队列尾,等待js引擎线程来处理。这个线程就是定时器线程。 - 异步请求线程
当执行到一个http异步请求时,便把异步请求事件添加到异步请求线程,等收到响应(准确来说应该是http状态变化),把回调函数添加到事件队列,等待js引擎线程来执行
- gui线程
BFC(Block formatting context)直译为"块级格式化上下文"
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算。
如何创建BFC
1、float的值不是none。
2、position的值不是static或者relative。
3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex
4、overflow的值不是visible
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素
箭头函数
箭头函数相当于匿名函数, 不绑定this、没有prototype属性、不绑定arguments
this 是指向词法作用域,由上下文确定
Array
# 改变原数组的方法
pop, push, shift. unshift, sort, reverse, splice
# 不改变原数组的方法
concat, valueOf, join, slice,lastIndexOf, toLocaleString // 返回新数组
词法作用域和动态作用域
- 词法作用域(静态作用域)是在
书写代码
或者说定义时确定的,而动态作用域是在运行时
确定的。
词法作用域关注函数在何处声明
,而动态作用域关注函数从何处调用
,其作用域链是基于运行时的调用栈的。
// 词法作用域
function foo() {
console.log(a) //2
}
function bar() {
var a = 3
foo()
}
var a = 2
bar()
// 动态作用域
function foo() {
console.log(a) //3
}
function bar() {
var a = 3
foo()
}
var a = 2
bar()