chen-jinrui / daydayup Goto Github PK
View Code? Open in Web Editor NEWlearn something
learn something
webpack配置ProvidePlugin后,在使用时将不再需要import和require进行引入,直接使用即可。
let arr = [1,[2,[[3,4],5],6]];
function oneDimensionalArray (arr) {
let arr1 = (arr + '').split(','); // 将数组转字符串后再以逗号分隔转为数组
let arr2 = arr1.map(function(x){
return Number(x);
});
return arr2;
}
console.log(oneDimensionalArray(arr));
let arr = [1,[2,3],[4,5]];
console.log([].concat.apply([],arr));
let arr = [1,[2,[[3,4],5],6]];
let arr2 = arr.join(',').split(',');
console.log(arr2);//["1", "2", "3", "4", "5", "6"]
//或
let c=[1,3,4,5,[6,[0,1,5],9],[2,5,[1,5]],[5]];
console.log(c.toString().split(','))
let arr = [1, [2, [[3, 4], 5], 6]];
let newArr = [];
function oneDimensionalArray(arr) {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
oneDimensionalArray(arr[i]);
} else {
newArr.push(arr[i]);
}
}
}
oneDimensionalArray(arr);
console.log(newArr); //[1, 2, 3, 4, 5, 6]
use strict';
let arr = [1,[2,[[3,4],5],6]];
const flatten = arr => arr.reduce(
(acc,val) => acc.concat(Array.isArray(val)? flatten(val):val),[]
)
console.log(flatten(arr));//[1, 2, 3, 4, 5, 6]
splice(para1, para2, value1, value2): 更改原数组,删除,添加
slice(para1, para2) 截取到新的数组
split: 字符串分割
接下来,浏览器的工作就是确定每一个元素的位置了。我们的基本原则仍然不变,就是尽可能流式地处理上一步骤的输出。
浏览器最基本的排版方案是正常流排版,它包含了顺次排布和折行等规则,我们把它叫做正常流。浏览器的文字排版遵循公认的文字排版规范,文字排版是一个复杂的系统,它规定了行模型和文字在行模型中的排布。行模型规定了行顶、行底、文字区域、基线等对齐方式。
浏览器又可以支持元素和文字的混排,元素被定义为占据长方形的区域,还允许边框、边距和留白,这个就是所谓的盒模型。
在正常流的基础上,浏览器还支持两类元素:绝对定位元素和浮动元素。
正常流是唯一一个文字和盒混排的排版方式
advance代表每一个文字排布后在主轴上的前进距离,它跟文字的宽/高不相等,是字体中最重要的属性。
除了字体提供的字形本身包含的信息,文字排版还受到一些CSS属性影响,如line-height、letter-spacing、word-spacing等。
在正常流的文字排版中,多数元素被当作长方形盒来排版,而只有display为inline的元素,是被拆成文本来排版的
display值为inline的元素中的文字排版时会被直接排入文字流中,inline元素主轴方向的margin属性和border属性(例如主轴为横向时的margin-left和margin-right)也会被计算进排版前进距离当中。
在正常流中,display不为inline的元素或者伪元素,会以盒的形式跟文字一起排版。多数display属性都可以分成两部分:内部的排版和是否inline,带有inline-前缀的盒,被称作行内级盒。
浏览器对行的排版,一般是先行内布局,再确定行的位置,根据行的位置计算出行内盒和文字的排版位置。
块级盒比较简单,它总是单独占据一整行,计算出交叉轴方向的高度即可。
position属性为absolute的元素,我们需要根据它的包含块来确定位置,这是完全跟正常流无关的一种独立排版模式,逐层找到其父级的position非static元素即可。
float元素非常特别,浏览器对float的处理是先排入正常流,再移动到排版宽度的最左/最右(这里实际上是主轴的最前和最后)。
axios.defaults.withCredentials = true 和后端 session 确认身份相关
cookie里保存了sessionid
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if(index === 0) {
sums[index] = '合计';
return;
}
const values = data.map(item => Number(item[column.property]));
if(!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) =>{
const value = Number(curr);
if(!isNaN(value)){
return prev + curr;
} else {
return prev;
}
}, 0);
} else {
sums[index] = '';
}
});
return sums;
}
Set 和 Map 主要的应用场景在于 数据重组 和 数据储存
Set 是一种叫做集合的数据结构,Map 是一种叫做字典的数据结构
ES6 新增的一种新的数据结构,类似于数组,但成员是唯一且无序的,没有重复的值。
Set 本身是一种构造函数,用来生成 Set 数据结构。
new Set([iterable])
举个例子:
const s = new Set()
[1, 2, 3, 4, 3, 2, 1].forEach(x => s.add(x))
for (let i of s) {
console.log(i) // 1 2 3 4
}
// 去重数组的重复对象
let arr = [1, 2, 3, 2, 1, 1]
[... new Set(arr)] // [1, 2, 3]
Set 对象允许你储存任何类型的唯一值,无论是原始值或者是对象引用。
向 Set 加入值的时候,不会发生类型转换,所以5
和"5"
是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===
),主要的区别是**NaN
等于自身,而精确相等运算符认为NaN
不等于自身。**
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
let set1 = new Set()
set1.add(5)
set1.add('5')
console.log([...set1]) // [5, "5"]
Set 实例属性
constructor: 构造函数
size:元素数量
let set = new Set([1, 2, 3, 2, 1])
console.log(set.length) // undefined
console.log(set.size) // 3
Set 实例方法
add(value):新增,相当于 array里的push
delete(value):存在即删除集合中value
has(value):判断集合中是否存在 value
clear():清空集合
let set = new Set()
set.add(1).add(2).add(1)
set.has(1) // true
set.has(3) // false
set.delete(1)
set.has(1) // false
Array.from
方法可以将 Set 结构转为数组
const items = new Set([1, 2, 3, 2])
const array = Array.from(items)
console.log(array) // [1, 2, 3]
// 或
const arr = [...items]
console.log(arr) // [1, 2, 3]
keys():返回一个包含集合中所有键的迭代器
values():返回一个包含集合中所有值得迭代器
entries():返回一个包含Set对象中所有元素得键值对迭代器
forEach(callbackFn, thisArg):用于对集合成员执行callbackFn操作,如果提供了 thisArg 参数,回调中的this会是这个参数,没有返回值
let set = new Set([1, 2, 3])
console.log(set.keys()) // SetIterator {1, 2, 3}
console.log(set.values()) // SetIterator {1, 2, 3}
console.log(set.entries()) // SetIterator {1, 2, 3}
for (let item of set.keys()) {
console.log(item);
} // 1 2 3
for (let item of set.entries()) {
console.log(item);
} // [1, 1] [2, 2] [3, 3]
set.forEach((value, key) => {
console.log(key + ' : ' + value)
}) // 1 : 1 2 : 2 3 : 3
console.log([...set]) // [1, 2, 3]
Set 可默认遍历,默认迭代器生成函数是 values() 方法
Set.prototype[Symbol.iterator] === Set.prototype.values // true
所以, Set可以使用 map、filter 方法
let set = new Set([1, 2, 3])
set = new Set([...set].map(item => item * 2))
console.log([...set]) // [2, 4, 6]
set = new Set([...set].filter(item => (item >= 4)))
console.log([...set]) //[4, 6]
因此,Set 很容易实现交集(Intersect)、并集(Union)、差集(Difference)
let set1 = new Set([1, 2, 3])
let set2 = new Set([4, 3, 2])
let intersect = new Set([...set1].filter(value => set2.has(value)))
let union = new Set([...set1, ...set2])
let difference = new Set([...set1].filter(value => !set2.has(value)))
console.log(intersect) // Set {2, 3}
console.log(union) // Set {1, 2, 3, 4}
console.log(difference) // Set {1}
WeakSet 对象允许你将弱引用对象储存在一个集合中
WeakSet 与 Set 的区别:
属性:
constructor:构造函数,任何一个具有 Iterable 接口的对象,都可以作参数
const arr = [[1, 2], [3, 4]]
const weakset = new WeakSet(arr)
console.log(weakset)
方法:
var ws = new WeakSet()
var obj = {}
var foo = {}
ws.add(window)
ws.add(obj)
ws.has(window) // true
ws.has(foo) // false
ws.delete(window) // true
ws.has(window) // false
集合 与 字典 的区别:
const m = new Map()
const o = {p: 'haha'}
m.set(o, 'content')
m.get(o) // content
m.has(o) // true
m.delete(o) // true
m.has(o) // false
任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map
构造函数的参数,例如:
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
如果读取一个未知的键,则返回undefined
。
new Map().get('asfddfsasadf')
// undefined
注意,只有对同一个对象的引用,Map 结构才将其视为同一个键。这一点要非常小心。
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
上面代码的set
和get
方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get
方法无法读取该键,返回undefined
。
由上可知,Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
如果 Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键,比如0
和-0
就是一个键,布尔值true
和字符串true
则是两个不同的键。另外,undefined
和null
也是两个不同的键。虽然NaN
不严格相等于自身,但 Map 将其视为同一个键。
let map = new Map();
map.set(-0, 123);
map.get(+0) // 123
map.set(true, 1);
map.set('true', 2);
map.get(true) // 1
map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3
map.set(NaN, 123);
map.get(NaN) // 123
Map 的属性及方法
属性:
constructor:构造函数
size:返回字典中所包含的元素个数
const map = new Map([
['name', 'An'],
['des', 'JS']
]);
map.size // 2
操作方法:
遍历方法
const map = new Map([
['name', 'An'],
['des', 'JS']
]);
console.log(map.entries()) // MapIterator {"name" => "An", "des" => "JS"}
console.log(map.keys()) // MapIterator {"name", "des"}
Map 结构的默认遍历器接口(Symbol.iterator
属性),就是entries
方法。
map[Symbol.iterator] === map.entries
// true
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...
)。
对于 forEach ,看一个例子
const reporter = {
report: function(key, value) {
console.log("Key: %s, Value: %s", key, value);
}
};
let map = new Map([
['name', 'An'],
['des', 'JS']
])
map.forEach(function(value, key, map) {
this.report(key, value);
}, reporter);
// Key: name, Value: An
// Key: des, Value: JS
在这个例子中, forEach 方法的回调函数的 this,就指向 reporter
与其他数据结构的相互转换
Map 转 Array
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log([...map]) // [[1, 1], [2, 2], [3, 3]]
Array 转 Map
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log(map) // Map {1 => 1, 2 => 2, 3 => 3}
Map 转 Object
因为 Object 的键名都为字符串,而Map 的键名为对象,所以转换的时候会把非字符串键名转换为字符串键名。
function mapToObj(map) {
let obj = Object.create(null)
for (let [key, value] of map) {
obj[key] = value
}
return obj
}
const map = new Map().set('name', 'An').set('des', 'JS')
mapToObj(map) // {name: "An", des: "JS"}
Object 转 Map
function objToMap(obj) {
let map = new Map()
for (let key of Object.keys(obj)) {
map.set(key, obj[key])
}
return map
}
objToMap({'name': 'An', 'des': 'JS'}) // Map {"name" => "An", "des" => "JS"}
Map 转 JSON
function mapToJson(map) {
return JSON.stringify([...map])
}
let map = new Map().set('name', 'An').set('des', 'JS')
mapToJson(map) // [["name","An"],["des","JS"]]
JSON 转 Map
function jsonToStrMap(jsonStr) {
return objToMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"name": "An", "des": "JS"}') // Map {"name" => "An", "des" => "JS"}
WeakMap 对象是一组键值对的集合,其中的键是弱引用对象,而值可以是任意。
注意,WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。
WeakMap 中,每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的key则变成无效的),所以,WeakMap 的 key 是不可枚举的。
属性:
方法:
let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();
myWeakmap.set(myElement, {timesClicked: 0});
myElement.addEventListener('click', function() {
let logoData = myWeakmap.get(myElement);
logoData.timesClicked++;
}, false);
Object 与 Set
// Object
const properties1 = {
'width': 1,
'height': 1
}
console.log(properties1['width']? true: false) // true
// Set
const properties2 = new Set()
properties2.add('width')
properties2.add('height')
console.log(properties2.has('width')) // true
Object 与 Map
JS 中的对象(Object),本质上是键值对的集合(hash 结构)
const data = {};
const element = document.getElementsByClassName('App');
data[element] = 'metadata';
console.log(data['[object HTMLCollection]']) // "metadata"
但当以一个DOM节点作为对象 data 的键,对象会被自动转化为字符串[Object HTMLCollection],所以说,Object 结构提供了 字符串-值 对应,Map则提供了 值-值 的对应
本文始发于我的博客:Set、WeakSet、Map及WeakMap
Originally posted by @sisterAn in Advanced-Frontend/Daily-Interview-Question#6 (comment)
通过template扩展
1、table 部分
:row-key='getRowKeys'
:expand-row-keys="expands"
@expand-change="expandSelect"
2、column 部分 :参见官方示例
data:{
expands: [],
},
4、method 部分
【注】设置展开区域的具体内容,就是在 expandSelect 这个方法内设置
getRowKeys:function(row){
return row.id
},
expandSelect:function(row, expandedRows) {
var that = this
if (expandedRows.length) {
that.expands = []
if (row) {
that.expands.push(row.id)
}
}
else {
that.expands = []
}
},
对于loader,它就是转换器,把A文件进行编译转换成B文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程;
对于plugin,它就是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,例如
组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。
vue组件间通信的几种方式,如props、 $emit/ $on、vuex、 $parent / $children、 $attrs/ $listeners和provide/inject
方法一、 props / $emit
1.父组件向子组件传值
父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed
2.子组件向父组件传值(通过事件形式)
子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。
方法二、 $emit / $on
这种方法通过一个空的Vue实例作为**事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。
var Event = new Vue(); Event.$emit(事件名,数据); Event.$on(事件名,data=>{});
因为有时不确定何时会触发事件,一般会在 mounted 或 created 钩子中来监听。
方法三、vuex
方法四、 $attrs / $listeners
方法五、provide/inject
方法六、 $parent / $children & ref
之前有看过一步步实现的文章,如下:
采纳 JSC 引擎的术语,我们把宿主发起的任务
称为宏观任务,把 JavaScript 引擎发起的任务称为微观任务。
[[1,2],[3,4]].map(([a,b]) => a+b);
// [3,7]
function move({ x = 0, y = 0 } = {}) {
return [x, y]
}
move({x: 3, y: 4}); // [3, 4]
move({x:3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
// 和下面的写法不同
function move({x, y} = {x: 0, y: 0}) {
return [x, y]
}
move ({x: 3, y: 4}); // [3, 4]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
// 上面的代码为 move 的参数指定默认值
// undefined 会触发函数参数的默认值
[1, undefined, 3].map((x = 'yes') => x); // [1, 'yes', 3]
总结一下如何分析异步执行的顺序:
首先我们分析有多少个宏任务;
在每个宏任务中,分析有多少个微任务;
根据调用次序,确定宏任务中的微任务执行次序;
根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
确定整个顺序
把CSS规则应用到节点上,并给这棵朴素的DOM树添加上CSS属性
选择器的出现顺序,必定跟构建DOM树的顺序一致。这是一个CSS设计的原则,即保证选择器在DOM树构建到当前节点时,已经可以准确判断是否匹配,不需要后续节点信息。
CSS计算是把CSS规则应用到DOM树上,为DOM结构添加显示相关属性的过程
后代选择器 “空格”
总结:从外到内,再从内到外
chrome浏览器的主要进程
@原文:https://juejin.im/post/5cda1492e51d453a8f348c02
Renderer进程的主要线程
任务队列
事件循环
宏任务
不同任务源的任务会放入不同的任务队列里,浏览器根据自己的算法来决定先取哪个队列里的任务。
宏任务至少有一个任务队列,微任务只有一个任务队列
微任务
哪些异步事件是微任务?Promise的回调、MutationObserver的回调以及nodejs中process.nextTick的回调。
宏任务和宏任务之间,积压的所有微任务会一次性执行完毕
对浏览器的实现者来说,他们做的事情,就是把一个URL变成一个屏幕上显示的网页。
这个过程是这样的:
一,通讯的部分:
HTTP协议是基于TCP协议出现的,对TCP协议来说,TCP协议是一条双向的通讯通道,HTTP在TCP的基础上,规定了Request-Response的模式。这个模式决定了通讯必定是由浏览器端首先发起的。
HTTP是纯粹的文本协议,它是规定了使用TCP协议来传输文本格式的一个应用层协议。
在HTTP协议的基础上,HTTPS和HTTP2规定了更复杂的内容,但是它基本保持了HTTP的设计**,即:使用上的Request-Response模式。
HTTPS有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。
HTTPS是使用加密通道来传输HTTP的内容。但是HTTPS首先与服务端建立一条TLS加密通道。TLS构建于TCP协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS跟HTTP没有任何区别。
HTTP 2是HTTP 1.1的升级版本,HTTP 2.0 最大的改进有两点,一是支持服务端推送,二是支持TCP连接复用。
服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。
TCP连接复用,则使用同一个TCP连接来传输多个HTTP请求,避免了TCP连接建立时的三次握手开销,和初建TCP连接时传输窗口小的问题。
折叠所有区域代码的快捷: ctrl + k ctrl + 0 ;
使用路由对象的resolve方法解析路由,可以得到location、router、href等目标路由的信息。得到href就可以使用window.open开新窗口了。
const {href} = this.$router.resolve({
name: "statistics-explain",
params: {
classID: id,
examSubjectID: this.planClassData.examSubjectID,
studentStatus: 0
}
});
window.open(href, '_blank');
node -pe "require('url').parse('/test?q=1', true)"
运行结果:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?q=1',
query: { q: '1' },
pathname: '/test',
path: '/test?q=1',
href: '/test?q=1'
}
Q1: 为什么有的编程规范要求用 void 0 代替 undefined ?
Q2: 字符串有最大长度吗?
Q3: 0.1+0.2 为什么不等于 0.3?
Q4: ES6新加入的 Symbol 是个什么东西?
Q5: 为什么给对象添加的方法能用在基本类型上?
A1: 因为JavaScript的代码 undefined 是一个变量,而并非是一个关键字,为了避免无意中被篡改,用void 0 获取 undefined 值
A2: String 有最大长度为 2^53 - 1 但是这个所谓的最大长度 并非是理解的字符数;因为 String 的意义并非”字符串“,而是字符串的 UTF16编码。JavaScript中的字符串是永远无法变更的,一旦字符串构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。
A3: JavaScript 中的 Number 类型基本符合IEEE规定的双精度浮点数规则,JavaScript为了表达几个额外的语言场景,规定了几个例外的情况: NaN,Infinity,-Infinity。
另外要注意的是:JavaScript中有 +0 和 -0,区分 +0 和 -0的方式是检测 1/x 是 Infinity 还是 -Infinity。
根据双精度浮点数的定义 Number 类型中有效的整数范围是 -0x1fffffffffffff 至 0x1fffffffffffff, 所以 Number 无法精确表示此范围外的整数。
同样根据浮点数的定义,非整数的 Number 类型无法用 == (===也不行)来比较。这就是为什么 0.1 + 0.2 != 0.3 的原因。浮点数运算的精度问题导致两侧并不是严格相等,而是相差了很微小的值。正确的比较方法是使用JavaScript提供的最小精度值。 Math.abs(0.1+0.2-03) <=Number.EPSILON j结果为 true
A4:
git rm -r --cached .
git add .
git commit -m 'update .gitignore'
<link rel="preload">
– when you’ll need a resource in a few seconds
<link rel="prefetch">
– when you’ll need a resource on a next page
<link rel="preconnect">
– when you know you’ll need a resource soon, but you don’t know its full url yet
<link rel="dns-prefetch">
– also when you know you’ll need a resource soon, but you don’t know its full url yet (for older browsers)
<link rel="prerender">
– when you’re certain users will navigate to a specific page, and you want to speed it up
var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);
for (let p of searchParams) {
console.log(p);
}
searchParams.has("topic") === true; // true
searchParams.get("topic") === "api"; // true
searchParams.getAll("topic"); // ["api"]
searchParams.get("foo") === ""; // true
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
searchParams.set("topic", "More webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
searchParams.delete("topic");
searchParams.toString(); // "q=URLUtils.searchParams"
会把axios 默认的 Content-Type: application/json 修改为 ‘x-www-form-urlencoded’
使用URLSearchParams,将原本默认的contenttype变为x-www-form-urlencoded,表单数据一般后端框架都能处理
记忆技巧
apply:最多只能有两个参数——新this对象和一个数组argArray
call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。
实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。
async/await 是 ES2016 新加入的特性,它提供了用 for、if 等代码结构来编写异步的方
式。它的运行时基础是 Promise
async 函数必定返回 Promise,我们把所有返回 Promise 的函数都可以认为是异步函数。
async 函数是一种特殊语法,特征是在 function 关键字之前加上 async 关键字,这样,
就定义了一个 async 函数,我们可以在其中使用 await 来等待一个 Promise。
async 函数强大之处在于,它是可以嵌套的。我们在定义了一批原子操作的情况下,可以
利用 async 函数组合出新的 async 函数。
后端拿数据 有 流的方式 和 对象的方式,用流的方式可以获取到;前端更改传递参数的方式(使用qs)
对象的键名只能是字符串和Symbol类型
其他类型的键名会被转化为字符串类型
对象转字符串会默认调用 toString 方法
git remote -v 查看远程仓库信息
git remote set-url origin [new_remote_repository_address] 修改关联远程仓库地址
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
浏览器将自己支持的一套加密规则发送给网站。
网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
获得网站证书之后浏览器要做以下工作:
a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
4.网站接收浏览器发来的数据之后要做以下的操作:
a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
b) 使用密码加密一段握手消息,发送给浏览器。
5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点。
vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。
在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种是map映射,另一种是遍历查找。相比而言。map映射的速度更快。
这是今天在 Advanced-Frontend组织 看到一个比较有意思的题目。
主要是讲JS的映射与解析
早在 2013年, 加里·伯恩哈德就在微博上发布了以下代码段:
['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]
parseInt()
函数解析一个字符串参数,并返回一个指定基数的整数 (数学系统的基础)。
const intValue = parseInt(string[, radix]);
string
要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。
radix
一个介于2和36之间的整数(数学系统的基础),表示上述字符串的基数。默认为10。
返回值
返回一个整数或NaN
parseInt(100); // 100
parseInt(100, 10); // 100
parseInt(100, 2); // 4 -> converts 100 in base 2 to base 10
注意:
在radix
为 undefined,或者radix
为 0 或者没有指定的情况下,JavaScript 作如下处理:
更多详见parseInt | MDN
map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
var new_array = arr.map(function callback(currentValue[,index[, array]]) {
// Return element for new_array
}[, thisArg])
可以看到callback
回调函数需要三个参数, 我们通常只使用第一个参数 (其他两个参数是可选的)。
currentValue
是callback 数组中正在处理的当前元素。
index
可选, 是callback 数组中正在处理的当前元素的索引。
array
可选, 是callback map 方法被调用的数组。
另外还有thisArg
可选, 执行 callback 函数时使用的this 值。
const arr = [1, 2, 3];
arr.map((num) => num + 1); // [2, 3, 4]
更多详见Array.prototype.map() | MDN
回到我们真实的事例上
['1', '2', '3'].map(parseInt)
对于每个迭代map
, parseInt()
传递两个参数: 字符串和基数。
所以实际执行的的代码是:
['1', '2', '3'].map((item, index) => {
return parseInt(item, index)
})
即返回的值分别为:
parseInt('1', 0) // 1
parseInt('2', 1) // NaN
parseInt('3', 2) // NaN, 3 不是二进制
所以:
['1', '2', '3'].map(parseInt)
// 1, NaN, NaN
由此,加里·伯恩哈德例子也就很好解释了,这里不再赘述
['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]
如果您实际上想要循环访问字符串数组, 该怎么办? map()
然后把它换成数字?使用编号!
['10','10','10','10','10'].map(Number);
// [10, 10, 10, 10, 10]
本文始发于我的博客:['1', '2', '3'].map(parseInt) what & why ?
Originally posted by @sisterAn in Advanced-Frontend/Daily-Interview-Question#4 (comment)
用git checkout branch -- filename
1.词(token)是如何被拆分的
浏览器是如何用代码实现,我们设想,代码开始从HTTP协议收到的字符流读取字符。我们每读入一个字符,其实都要做一次决策,而且这些决定是跟“当前状态”有关的。在这样的条件下,浏览器工程师要想实现把字符流解析成词(token),最常见的方案就是使用状态机。
2.状态机
绝大多数语言的词法部分都是用状态机实现的。
状态机的初始状态,我们仅仅区分 “< ”和 “非<”:
用状态机做词法分析,其实正是把每个词的“特征字符”逐个拆开成独立状态,然后再把所有词的特征字符链合并起来,形成一个联通图结构。
接下来就是代码实现的事情了,在C/C++和JavaScript中,实现状态机的方式大同小异:我们把每个函数当做一个状态,参数是接受的字符,返回值是下一个状态函数。
词法分析器接受字符的方式很简单,就像下面这样:
`function HTMLLexicalParser(){
//状态函数们……
function data() {
// ……
}
function tagOpen() {
// ……
}
// ……
var state = data;
this.receiveInput = function(char) {
state = state(char);
}
}`
至此,我们就把字符流拆成了词(token)了。
构建DOM树
接下来我们要把这些简单的词变成DOM树,这个过程我们是使用栈来实现的,任何语言几乎都有栈
function HTMLSyntaticalParser(){ var stack = [new HTMLDocument]; this.receiveInput = function(token) { //…… } this.getOutput = function(){ return stack[0]; } }
通过这个栈,我们可以构建DOM树:
对称加密:
发送方和接收方需要持有同一把密钥,发送消息和接收消息均使用该密钥。相对于非对称加密,对称加密具有更高的加解密速度,但双方都需要事先知道密钥,密钥在传输过程中可能会被窃取,因此安全性没有非对称加密高。
非对称加密:
接收方在发送消息前需要事先生成公钥和私钥,然后将公钥发送给发送方。发送放收到公钥后,将待发送数据用公钥加密,发送给接收方。接收到收到数据后,用私钥解密。
在这个过程中,公钥负责加密,私钥负责解密,数据在传输过程中即使被截获,攻击者由于没有私钥,因此也无法破解。
非对称加密算法的加解密速度低于对称加密算法,但是安全性更高。
几个名词
Promise是一个表现为状态机的异步容器。
它有以下几个特点:
状态不受外界影响。Promise只有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。状态只能通过Promise内部提供的resolve()和reject()函数改变。
状态只能从pending变为fulfilled或者从pending变为rejected。并且一旦状态改变,状态就会被冻结,无法再次改变。
如果状态发生改变,任何时候都可以获得最终的状态,即便改变发生在前。这与事件监听完全不一样,事件监听只能监听之后发生的事件。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.