--209/7/25 素衣
数据类型
基础数据类型:数字(number),字符串(string),布尔值(boolean),underfined, null,symbol,BigInt。
引用数据类型:对象(Object)。
Number
string
属性
length 字符串长度
constructor 构造函数
_ proto_ String.prototype 型对象,可向对象添加属性或方法
| 方法 | 作用 |
|---|---|
| charAt(index) | 返回指定位置的字符 |
| charCodeAt(index) | 返回指定位置字符的unicode编码 |
| concat(elements) | 链接两个或多个字符串,返回新的字符串 |
| indexOf(str) lastIndexOf(str) |
返回指定字符在字符串首次出现的位置 |
| match(regexp) | 查找到正则表达式的匹配 |
| search(regexp) | 返回符合正则表达式的位置 |
| slice(start, end) | 截取字符串的片段并返回,左闭右开 |
| replace(searchValue, replaceValue) | 在字符串中查找匹配的字符串,替换为新的字符串并返回 |
| split(separator) | 将字符串按传入字符分割成字符串数组 |
| substr(start, length) | 返回从起始位置开始指定数目的字符 |
| substring(start, end) | 截取字符串的片段并返回,左闭右开 |
| toLowerCase() toUpperCase() toLocalLowerCase() toLocalUpperCase() |
将字符串转换为小/大写 |
| trim() trimLeft() trimRight |
去掉字符串两边的空白 |
| valueOf() toString() |
返回字符串原始值 |
| localCompare(str) | 用特定的顺序来比较两个字符串 |
| String.fromCharCode(codes) String.fromCodePonit(codes) |
将unicode编码转为字符 |
| endsWith(searchSring, postion) startsWith(searchSring, postion) |
判断字符串是否以给定字符串结尾 |
| includes(searchSring, postion) | 判断字符串是否包含另一个字符串 |
| repeat(count) | 返回新的字符串,包含链接在一起指定数量的副本 |
| String.raw() | 用来处理模板字符串 |
| normalize(form) | 将字符串正规化 |
| padEnd(targetLength, padString) padStart(targetLength, padString) |
将字符串填充到指定长度 |
Array
Array.of
Array.of用于将参数依次转化为数组中的一项,然后返回这个新数组,而不管这个参数是数字还是其它。
Array.of(8.0); // [8]
Array(8.0); // [empty × 8]
Array.from
Array.from的设计初衷是快速便捷的基于其他对象创建新数组,准确来说就是从一个类似数组的可迭代对象创建一个新的数组实例,说人话就是,只要一个对象有迭代器,Array.from就能把它变成一个数组(当然,是返回新的数组,不改变原对象)。
var obj = {0: 'a', 1: 'b', 2:'c', length: 3};
Array.from(obj, function(value, index){
//console.log(value, index, this, arguments.length);
return value.repeat(3); //必须指定返回值,否则返回undefined
}, obj);
['aaa','bbb','ccc']
Array.isArray
Array.isArray用来判断一个变量是否数组类型。JS的弱类型机制导致判断变量类型是初级前端开发者面试时的必考题,一般我都会将其作为考察候选人第一题,然后基于此展开。在ES5提供该方法之前,我们至少有如下5种方式去判断一个值是否数组:
var a = [];
// 1.基于instanceof
a instanceof Array;
// 2.基于constructor
a.constructor === Array;
// 3.基于Object.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(a);
// 4.基于getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype;
// 5.基于Object.prototype.toString
Object.prototype.toString.apply(a) === '[object Array]';
改变自身的方法
pop、push、reverse、shift、sort、splice、unshift,以及两个ES6新增的方法copyWithin 和 fill。
| 方法 | 作用 |
|---|---|
| pop | 删除一个数组中的最后的一个元素,并且返回这个元素 |
| push | 添加一个或者多个元素到数组末尾,并且返回数组新的长度 |
| reverse | 颠倒数组中元素的位置,该方法返回对数组的引用 |
| shift | 删除数组的第一个元素,并返回这个元素 |
| sort | 数组元素进行排序,并返回这个数组 |
| splice | 用新元素替换旧元素的方式来修改数组。 |
| unshift | 在数组开始处插入一些元素(就像是栈底插入),并返回数组新的长度 |
| copyWithin | 数组内元素之间的替换,即替换元素和被替换元素均是数组内的元素 |
| fill | 将数组指定区间内的元素替换为某个值 |
不会改变自身的方法
concat、join、slice、toString、toLocateString、indexOf、lastIndexOf、未标准的toSource以及ES7新增的方法includes。
| 方法 | 作用 |
|---|---|
| concat | 将传入的数组或者元素与原数组合并,组成一个新的数组并返回 |
| join | 将数组中的所有元素连接成一个字符串并返回 |
| slice | 将数组中一部分元素浅复制存入新的数组对象,并且返回这个数组对象 |
| toString | 返回数组的字符串形式 |
| toLocaleString | |
| indexOf | 用于查找元素在数组中第一次出现时的索引,如果没有,则返回-1 |
| lastIndexOf | 用于查找元素在数组中最后一次出现时的索引,如果没有,则返回-1 |
| includes | 判断当前数组是否包含某个指定的值,如果是,则返回 true,否则返回 false |
| toSource | 返回数组的源代码(目前fireFox实现) |
遍历方法
forEach、every、some、filter、map、reduce、reduceRight 以及ES6新增的方法entries、find、findIndex、keys、values
| 方法 | 作用 |
|---|---|
| forEach | 指定数组的每项元素都执行一次传入的函数,返回值为undefined |
| every | 使用传入的函数测试所有元素,只要其中有一个函数返回值为 false,那么该方法的结果为 false;如果全部返回 true,那么该方法的结果才为 true |
| some | 测试数组元素时,只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false |
| filter | 使用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。它就好比一个过滤器,筛掉不符合条件的元素 |
| map | 遍历数组,使用传入函数处理每个元素,并返回函数的返回值组成的新数组 |
| reduce | 数组中的每个值(从左至右) 开始合并,最终为一个值 |
| reduceRight | 除了与reduce执行方向相反外,其他完全与其一致 |
| entries | 返回一个数组迭代器对象,该对象包含数组中每个索引的键值对 |
| find& | 返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回undefined |
| findIndex | 它返回数组中第一个满足条件的元素的索引(如果有的话)否则返回-1 |
| keys | 返回一个数组索引的迭代器 |
| values | 返回一个数组迭代器对象,该对象包含数组中每个索引的值 |
| Symbol.iterator(ES6) | 同 values 方法功能相同 |
- 所有插入元素的方法, 比如 push、unshift,一律返回数组新的长度;
- 所有删除元素的方法,比如 pop、shift、splice 一律返回删除的元素,或者返回删除的多个元素组成的数组;
- 部分遍历方法,比如 forEach、every、some、filter、map、find、findIndex,它们都包含
function(value,index,array){}和thisArg这样两个形参。
实现map方法
Array.prototype.fakeMap = function(fn, context) {
if(typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
let arr = this;
let temp = [];
for(let i = 0; i < arr.length; i++) {
let result = fn.call(context,arr[i], i, arr);
temp.push(result);
}
return temp;
}
实现filter方法
Array.prototype.fakeFilter = function(fn, context) {
if(typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
let arr = this;
let temp = [];
for(let i = 0; i < arr.length; i++) {
let result = fn.call(context, arr[i], i, arr);
if(result) {
temp.push(result);
}
}
return temp;
}
Object
Object.defineProperty()
Object.defineProperty(obj, prop, descriptor) // obj 定义属性的对象 // prop 要定义或者修改的名称或属性 // 正在定义或修改属性的描述符
返回值
传递给函数的对象
descriptor
value:属性的值(不用多说了)
writable:如果为false,属性的值就不能被重写,只能为只读。(默认:false)
configurable:总开关,一旦为false,就不能再设置他的(value,writable,configurable)(默认:false)
enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。(默认:false)
get:
set:
使用Object.defineProperty为对象新增属性时,该属性的writable,configurable,enumerable默认为false
设置value等时,不可设置get set。
var obj = {};
obj.a = 1;
Object.defineProperty(obj, "b",
{
value: 2
});
console.log(Object.getOwnPropertyDescriptor(obj, "a")); // 打印"{value: 1, writable: true, enumerable: true, configurable: true}"
console.log(Object.getOwnPropertyDescriptor(obj, "b")); // 打印"{value: 2, writable: false, enumerable: false, configurable: false}"
MVVM框架双向绑定
function defineReactive(obj, key, value) {
var dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
if (Dep.target) {
dep.depend()
}
return value
},
set: function reactiveSetter(newVal) {
if (value === newVal) {
return
} else {
value = newVal
dep.notify()
}
}
})
}
Object.assign()
Object.assign(target,source) 中将sources对象中所有可枚举的属性的值复制到目标的对象中,其会返回目标对象。
target = Object.assign({}, traget, source);
Object.getOwnPropertyDescriptor(obj,prop)
该方法是用于如果prop属性存在对象obj上,则返回其属性描述符,如果不存在就返回undefined。该属性描述符由下面的属性所组成。
【value】表示属性的值,仅针对数据属性描述符有效
【writable】当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)
【configurable】 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。
【enumerable】当且仅当指定对象的属性可以被枚举出时,为 true。
【get】获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。
【set】获取该属性的设置器函数(setter)。如果没有设置器,该值为undefined。(仅针对包含访问器或设置器的属性描述有效) 该方法能够在IE8及以上的浏览器上运行。
Object.getOwnPropertyNames(obj)
该方法返回obj上所有自身可枚举和不可枚举的属性(不包括原型链上的属性),如果传入的obj不是数组,则会报错。该方法的兼容IE9及以上的浏览器。
Object.getPrototypeOf(obj)
该方法返回对象的原型对象,如果没有的话,则返回null。需要指出的是,对于函数对象,其返回的并不是显式原型(prototype),而是隐式原型(proto),该方法兼容IE9及以上的浏览器。
Object.is(val1,val2)
该方法是确定两个值是否是相同的值,这个方法与===相比,其会将-0和+0看成不等,并且对于两个NaN的比较,Object.is()会看成是相等的,而===会将0、-0、+0看成相等的,两个NaN看成不等。
Object.is(0,-0)//false
Object.is(-0,-0);//true
Object.is(NaN,0/0); //true
Object.is(5,5/1); //true
Object.preventExtensions()
该方法可以让一个对象永远不能添加新的属性。
Object.seal(obj)
其对一个对象进行密封,并返回被密封的对象,这些对象都是不能够添加属性,不能删除已有属性,以及不能够修改已有属性的可枚举型、可配置型、可写性。
Object.freeze(obj)
该方法将obj对象冻结,其任何属性都是不可以被修改的。
浅冻结
Object.keys(obj)
该方法会返回obj上所有可以进行枚举的属性的字符串数组
Object.values(obj)
该方法会返回obj上所有可以进行枚举的属性的值
getOwnPropertySymbols(obj)
该方法返回obj对象上自身的(非继承的)所有Symbol属性键。
call,apply,bind解析
三个方法都是为了改变this指向问题。
apply,call二者来言,作用完全一样,只是接受参数的方式不太一样
call(this, arg1, arg2)
apply(this, [arg1, arg2])
var arr1 = [12, '12'];
var arr2 = ['b','123'];
Array.prototype.push.call(arr1, ...arr2);
Array.prototype.push.apply(arr1, arr2);
arr1 // [12, "12", "b", "123"]
bind()方法会创建一个新函数
var foo = {x: 3};
var bar = function() {
console.log(this.x);
}
bar();// undefined
var func = bar.bind(foo);
func();//3
实现apply
Function.prototype.myApply = function(context,args) {
context = context || window;
args = args ? args : [];
const key = Symbol();
context[key] = this;
const result = context[key](...args);
delete context[key];
return result;
}
实现call
Funtion.prototype.mayCall = function(context, ...args) {
context = context || window;
args = args ? args : [];
const key = Symbol();
context[key] = this;
const result = context[key](...args);
delete context[key];
return result;
}
实现bind
Function.prototype.myBind = function(context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1); // 接受除第一个参数外的参数,作为传递用
return function() {
var bindArgs = Array.prototype.slice.call(arguments);// 接受返回函数的arguments数组
self.apply(context, args.concat(bindArgs));
}
}
浏览器
hash与history路由
hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:www.abc.com/#/hello,has… 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
winow.location.hash=1
// https://www.baidu.com/#1
history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)。
这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
window.history.pushState(data,title,url);
history.pushState({a:1},'suyi','data=1');
//https://www.baidu.com/data=1
history.state
// {a: 1}
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 www.abc.com/book/id。如果后… /book/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
HTTP
1、概述
HTTP 全称是 HyperText Transfer Protocal ,即:超文本传输协议,从 1990 年开始就在 WWW 上广泛应用,是现今在 WWW 上应用最多的协议,HTTP 是应用层协议,当你上网浏览网页的时候,浏览器和 web 服务器之间就会通过 HTTP 在 Internet 上进行数据的发送和接收。HTTP 是一个基于请求/响应模式的、无状态的协议。即我们通常所说的 Request/Response
2、特点
- 支持客户端/服务器模式
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快
- 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记
- 无连接:无连接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接,采用这种方式可以节省传输时间
- 无状态:HTTP 协议是无状态协议。无状态是指协议对于事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能会导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就比较快
请求方法
| 方法名 | 功能 |
|---|---|
| GET | 向指定的资源发出“显示”请求,使用 GET 方法应该只用在读取数据上,而不应该用于产生“副作用”的操作中 |
| POST | 指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求文本中。这个请求可能会创建新的资源或者修改现有资源,或两者皆有。 |
| PUT | 向指定资源位置上传其最新内容 |
| DELETE | 请求服务器删除 Request-URI 所标识的资源 |
| OPTIONS | 使服务器传回该资源所支持的所有HTTP请求方法。用*来代替资源名称,向 Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作 |
| HEAD | 与 GET 方法一样,都是向服务器发出指定资源的请求,只不过服务器将不传回资源的本文部分,它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中关于该资源的信息(原信息或称元数据) |
| TRACE | 显示服务器收到的请求,主要用于测试或诊断 |
| CONNECT | HTTP/1.1 中预留给能够将连接改为通道方式的代理服务器。通常用于 SSL 加密服务器的链接(经由非加密的 HTTP 代理服务器) |
请求头
请求和响应常见通用的 Header
| 名称 | 作用 |
|---|---|
| Content-Type | 请求体/响应体的类型,如:text/plain、application/json |
| Accept | 说明接收的类型,可以多个值,用,(英文逗号)分开 |
| Content-length | 请求体/响应体的长度,单位字节 |
| Content-Encoding | 请求体/响应体的编码格式,如 gzip、deflate |
| Accept-Encoding | 告知对方我方接受的 Content-Encoding |
| ETag | 给当前资源的标识,和Last-Modified、If-None-Match、If-Modified-Since配合,用于缓存控制 |
| Cache-Control | 取值一般为no-cache、max-age=xx,xx为整数,表示资源缓存有效期(秒) |
常见的请求 Header
| 名称 | 作用 |
|---|---|
| Authorization | 用于设置身份认证信息 |
| User-Agent | 用户标识,如:OS 和浏览器的类型和版本 |
| If-Modified-Since | 值为上一次服务器返回的Last-Modified值,用于确定某个资源是否被更改过,没有更改过就从缓存中读取 |
| If-None-Match | 值为上一次服务器返回的 ETag 值,一般会和If-Modified-Since |
| Cookie | 已有的Cookie |
| Referer | 标识请求引用自哪个地址,比如你从页面 A 跳转到页面 B 时,值为页面 A 的地址 |
| Host | 请求的主机和端口号 |
响应状态行
浏览器输入 URL 地址后发生的事情
浏览器向 DNS 服务器查找输入 URL 对应的 IP 地址。
NS 服务器返回网站的 IP 地址。
浏览器根据 IP 地址与目标 web 服务器在 80 端口上建立 TCP 连接。
浏览器获取请求页面的 HTML 代码。
浏览器在显示窗口内渲染 HTML 。
窗口关闭时,浏览器终止与服务器的连接。
JS事件循环机制
JavaScript 语言的一大特点就是单线程, 事件循环的执行机制: 循环首先从宏任务开始,遇到script,生成执行上下文,开始进入执行栈,可执行代码入栈,依次执行代码,调用完成出栈。 执行过程中遇到上边提到的调度者,会同步执行调度者,由调度者将其负责的任务(回调函数)放到对应的任务队列中,直到主执行栈清空,然后开始执行微任务的任务队列。微任务也清空后,再次从宏任务开始,一直循环这一过程。
同步任务队列
异步任务队列
宏任务(task)
script(整体代码)
setTimeout, setInterval, setImmediate,
I/O
UI rendering ajax请求不属于宏任务,js线程遇到ajax请求,会将请求交给对应的http线程处理,一旦请求返回结果,就会将对应的回调放入宏任务队列,等请求完成执行。
微任务(jobs)
process.nextTick
Promise
Object.observe(已废弃)
MutationObserver(html5新特性)
在 Node 中,会优先清空 next tick queue,即通过process.nextTick 注册的函数,再清空 other queue,常见的如Promise;此外,timers(setTimeout/setInterval) 会优先于 setImmediate 执行,因为前者在 timer 阶段执行,后者在 check 阶段执行。
console.log('script start');
setTimeout(function() {
console.log('timeout1');
}, 10);
new Promise(resolve => {
console.log('promise1');
resolve();
setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
console.log('then1')
})
console.log('script end');
// script start
// promise1
// script end
// then1
// timeout1
// timeout2
Vue
生命周期
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
React
React 的设计遵循单向数据流模型 ,也就是说,数据均是由父组件流向子组件。
Hooks
让组件在不使用 class 的情况下拥有 state,所以就有了生命周期的概念,所谓的生命周期其实就是 useState、 useEffect() 和 useLayoutEffect()。
useEffect componentDidMount, componentDidUpdate ,componentWillUnmount
// componentDidMount/componentWillUnmount
useEffect(()=>{
// 需要在 componentDidMount 执行的内容
return function cleanup() {
// 需要在 componentWillUnmount 执行的内容
}
}, [])
生命周期
挂载阶段
constructorstatic getDerivedStateFromPropsrendercomponentDidMount
更新阶段
static getDerivedStateFromPropsshouldComponentUpdaterendergetSnapshotBeforeUpdatecomponentDidUpdate
卸载阶段
componentWillUnmount
static getDerivedStateFromProps
static getDerivedStateFromProps: 该函数在挂载阶段和组件更新阶段都会执行,即每次获取新的props 或 state 之后都会被执行,在挂载阶段用来代替componentWillMount;在组件更新阶段配合 componentDidUpdate,可以覆盖 componentWillReceiveProps 的所有用法。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate: 该函数会在 render 之后, DOM 更新前被调用,用于读取最新的 DOM 数据。