解构赋值
数组或者对象解构赋值并设置默认值
资料见
const { name: assign = 'lisi'} = { name: 'zs', age: 18 }
const { sex: hasDefaultValue = 'lisi'} = { name: 'zs', age: 18 }
const [ arrFirstValue = 'first-value' ] = []
const [ , arrsecondValue = 'second-value' ] = ['red', 'yellow']
console.log('assign:', assign) // assign: zs
console.log('hasDefaultValue:', hasDefaultValue) // hasDefaultValue: lisi
console.log('arrFirstValue', arrFirstValue) // arrFirstValue: first-value
console.log('arrSecondValue', arrsecondValue) // arrFirstValue: first-value
decodeURIComponent()
作用:对编码后的url进行解码
decodeURIComponent('http%3A%2F%2Fwww.w3school.com.cn%2FMy%20first%2F')
// "http://www.w3school.com.cn/My first/"
this指向问题
- 谁调用this就指向谁(直接调用者)
const obj = {
a: 10,
b: {
a: 12,
fn: function() {
console.log(this.a)
}
}
}
obj.b.fn() // 12 <=直接调用者
- 箭头函数没有作用域,指向上一层
var id = 1
function fn() {
setTimeout(() => {
console.log(this.id)
})
}
fn({id: 66}) // 1
// 想要改变,可以使用call(),apply(),bind(),用法待补充todo
- var 定义的变量会挂载到window上 => window.变量名 = 值
- let 定义的变量不会
var usernames = 'zs'
function fn() {
console.log(this.usernames);
}
fn() // zs
let username = 'zs'
function fn() {
console.log(this.username);
}
fn() // undefined
new关键字
防抖和节流
防抖:触发事件后n秒才执行函数,如果在n秒内触发了事件,则会重新计算函数执行时间。
function debounce(fn, wait) {
let timer = null;
return function() {
const context = this;
const args = arguments;
timer && clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
}
}
节流:连续触发事件但在n秒内只执行一次
// 时间戳版本
function throttle(fn, wait) {
let perv = 0;
return function() {
const now = Date.now();
const content = this;
const args = arguments;
if (now - prev > wait) {
fn.apply(this, args);
perv = now;
}
}
}
// 定时器版本
funciton throttle(fn, wait) {
let timer = null;
return function() {
const context = this;
const args = arguments;
if (!timer) {
timer = setTimeout(() => {
timer = null;
fn.apply(context, args);
}, wait)
}
}
}
线程和进程
进程:一个进程就是一个程序的运行实例,启用一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码,运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。
线程:多线程可以并行处理任务,但是线程是不能单独存在的,它是由进程来启动和管理的,线程是依附于进程的。
进程和线程之间的关系
- 进程中的任意一线程执行出错,都会导致整个进程的崩溃
- 线程之间共享进程中的数据
- 当一个进程关闭之后,操作系统会回收进程所占用的内存
- 进程之间的内容相互隔离
从输入URL到页面展示,这中间发生了什么?
关注点:从进程间考虑
- 浏览器进程收到用户输入的url请求,通过进程间通信(IPC)把URL发送到网络进程
- 网络进程会首先在本地查找资源,如果本地有缓存直接将资源返回给浏览器进程
- 如果没有,进程网络请求流程
- 首先进程DNS域名解析,获取请求域名的服务器IP地址
- 利用IP地址和服务器进行TCP连接,建立连接之后,浏览器端会构建请求行、请求头等信息,并把该域名相关的cookie等数据附加到请求头中,然后向浏览器发送构建的请求信息
- 在接收到相应信息后,网络进程开始解析响应头,如果返回的是301、302则表示服务器需要浏览器重定向到其他URL,网络进程会读取重定向的地址,重新发起请求
- 会根据响应头返回的信息Content-Type中来对应处理
- 如果Content-Type返回的是html,则进行渲染进程的处理
- 浏览器进程在收到网络进程返回的响应数据之后,便向渲染进程发送‘提交文档’的消息
- 渲染进程收到消息之后,便向网络进程建立起管道
- 待文档数据处理完成后,渲染进程便向浏览器进程发送‘确认提交的消息
- 浏览器进程收到渲染进程的‘确认提交’的信息之后,会更新浏览器页面状态,包括安全状态、地址栏的URL、前进后退的历史状态,更新WEB页面。
- 渲染进程对文档进行页面解析和子资源加载,HTML 通过HTM 解析器转成DOM Tree(二叉树类似结构的东西),CSS按照CSS 规则和CSS解释器转成CSSOM TREE,两个tree结合,形成render tree(不包含HTML的具体元素和元素要画的具体位置),通过Layout可以计算出每个元素具体的宽高颜色位置,结合起来,开始绘制,最后显示在屏幕中新页面显示出来
函数柯里化
定义:一个函数原本有多个参数,只传入一个参数,生成一个新的函数,由新函数接收剩下的参数来运行得到结构。
【对对象属性访问的解析方法】 其他解析方法可以参数lodash源码
function fnByPath(path) {
return funciton fnByObj(obj) {
const paths = path.split('.');
let res = obj;
let prop = '';
while(prop = paths.shift()) {
res = res[prop];
}
return res;
}
}
箭头函数
箭头函数和普通函数的区别:
- this指向的是上一层执行环境的this,同时super,arguments,new.target这些值都是由外层的函数决定
- 不能通过new关键字调用,箭头函数没有construct方法,不能作为构造函数
- 没有原型,不存在prototype属性
- 不可以改变this的绑定
- 没有自己的arguments对象,如果要获取自己的,可以通过命名参数和不定参数(...reset)这两种形式访问函数的参数
- 不支持重复的命名参数
link和@import的区别
- 加载资源的限制:link是xhtml标签,除了加载css文件外,还可以加载RSS等其他事务,如加载模板等,而@import只能加载css文件
- 加载顺序:link会和页面并行加载,而@import会等页面加载完毕之后,再载入css文件
- 兼容性:link是xhmtl标签,没有兼容性问题,而@import不支持低版本的浏览器
- 改变样式:link标签是DOM标签,支持通过js控制DOM和修改样式,@import不支持。
常见的浏览器内核有哪些
- Trident: IE
- WebKit: Safari,旧版的Chrome
- Blink: Chrome,Opera
- Gecko: Firefox
ES5/ES6的继承除了写法之外还有什么区别?
- class声明会提升。但是不会初始化赋值。(类似于let、const)声明变量;
- class声明内部会启用严格模式;
- class的所有方法(包括静态方法和实例方法)都是不可枚举;
- class的所有方法(包括静态方法和实例方法)都没有原型对象,所以也没有constructor,不能通过new来调用;
- 必须通过new来调用class;
- class内部无法重写类型;
手写bind、call、apply
Array.prototype.MyCall = function(context) {
const args = [...arguments].slice(1);
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
}
Array.prototype.MyApply = function(context) {
const args = arguments[1] || [];
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
}
Array.prototype.MyBind = function(context) {
const args = [...arguments].slice(1);
return function () {
context.MyApply(context, args);
}
}