- 左右居中 text-align:center / margin: 0 auto / position: absotion; margin-top: -100px;
- 垂直居中 display: table-cell;vertical-align: middle / position: absotion; margin-top: -100px; / position: absolute;top: 0;bottom: 0;margin: auto;
- flex居中 display: flex;align-items:center;justify-content:center;
- 一个盒子中主要的属性就5个:width、height、padding、border、margin
- 两种类型
- IE盒模型,IE6之后就废弃了,width、height部分包含padding和border,对应box-sizing: border-box
- 标准盒模型,width、height部分不包含padding和border,对应box-sizing: content-box
简单类型:number string boolean symbol
复杂类型:object(null undefined array function)
简单类型是存储于栈中
复杂类型则是在栈中存储一个地址,然后将数据存储在堆中。然后通过栈中的地址去找到堆中的数据,他们之间存在一个引用(虚拟的)
存储数据分配了内存,那么就有必要再这些数据没用的时候进行回收,JS里面有GC 垃圾回收机制。GC垃圾回收 :如果一个对象没有被引用,它就是垃圾,将会被回收。
fn = new Foo()
fn.constructor = Foo
fn._proto_ = Foo.prototype
Foo.prototype.constructor = Object
Foo.prototype._proto_ = Object.prototype
Object.prototype._proto_ = null
// 所以fn通过_proto_指向Foo.prototype
// Foo.prototype通过_proto_只想Object.prototype
// 因为Object.prototype有toString方法,所以fn也有toString方法
// 这个就是js继承的实现基础
// 如果两个操作值都是数值,则进行数值比较
console.log(12 > 11) // true
// 如果两个操作值都是数值字符串或者数字,则都转换为数值进行比较
console.log('12' > 11) // true
// 如果两个操作值都是非数字字符串,则比较字符串对应的字符编码值
console.log('a' > 'b') // false
// 如果只有一个操作值是非数字字符串,另一个操作值是数值,非数字字符串转为NaN
// NaN是非常特殊的值,它不和任何类型的值相等,包括它自己,同时它与任何类型的值比较大小时都返回false。
console.log('a' > 11) // false
// 如果一个操作值是布尔值,则将其转换为数值,true是1 false是0
console.log(true < 2) // true
// 如果一个操作值为布尔值,则在比较之前先将其转换为数值
console.log(true == 1) // true
// 如果一个操作值为数值字符串,另一个操作值为数值,则通过Number()将字符串转换为数值
console.log('5' == 5) // true
// 如果一个操作值为非数值字符串,另一个操作值为数值,则通过Number()将非数字字符串转换NaN 永远是false
console.log('a' == 6) // false
// 如果一个操作值是对象,另一个不是,则调用对象的toString()方法,得到的结果按照前面的规则进行比较
// 如果两个操作值都是对象,则比较它们是不是指向同一个对象
const a = [1, 2, 3]
const b = '1,2,3'
const c = [1, 2, 3]
console.log(a == b) // a通过toString转换为1,2,3 所以为true
console.log(a == c) // 两者都是对象 不指向同一个对象 所以为false
// [1]通过toString转换为'1' '1'转化后为数字1 所以为true
console.log([1] == 1) // true
console.log([0] == false) // true
// 如果两者皆为null或undefined则返回true,否则返回false
console.log(null == undefined) // true
console.log(null == null) // true
console.log(null == 0) // false
// []通过toString转换为''然后转换为0 ![]转换为false然后转化为0 所以true
console.log([] == ![])
- 两边都是对象 看是否指向同一个对象 否则为false
- 一边是对象 对象toString变为字符串再比较
- 两边都是非数字字符串 转为ascii码
- 一边是非数字字符串 另一边是数字 非数字字符串转为NaN 永远false
- 数组字符串 布尔值 都转为数字 然后比较
js中没有块级作用域的概念
// 花括号内并不是块级作用域 外部都能访问到变量
if (true) {
var a = 1
}
console.log(a) // 1
for (var b = 0; b < 10; b++) {
}
console.log(b) // 10
如果要创建块级作用域有如下方法
- 用let替代var
// es6后 let定义的变量 有了块级作用域的概念 只能再花括号内访问到
if (true) {
let a = 1
}
console.log(a) // erro undefined
for (let b = 0; b < 10; b++) {
}
console.log(b) // erro undefined
// i不是块级作用域里的
let i;
for(i = 0; i < 5; i++){
setTimeout(function(){
console.log(i); // 5 5 5 5 5
},1000)
}
// i是块级作用域里的
for(let i = 0; i < 5; i++){
setTimeout(function(){
console.log(i); // 0 1 2 3 4
},1000)
}
- 用匿名函数自我执行
// a和b只能再函数内部访问 创建了函数内的块级作用域
(() => {
var a = 0
let b = 1
})()
console.log(a, b) // erro a and b undefined
- let能创造块级作用域 var不能 如上
- let不能变量提升 var可以
// 报错 因为let不能变量提升
function fn1(){
console.log(a);
let a = 1;
}
fn1();
// undefined 因为变量提升了 fn2相当于下面fn3
function fn2(){
console.log(a);
var a = 1;
}
fn2();
// 输出undefined
function fn3(){
var a;
console.log(a);
a = 1;
}
fn3();
- conts 用来声明常量,所谓常量就是物理指针不可以更改的变量
const a ; //报错,一旦声明变量,应该立即赋值
const b = 2; // 没问题
b = 3 //报错,因为定义常量之后不能成重新赋值
// 对于对象类型来说 不能改变指针指向
const c = []
c = [1, 2] // 报错 两者指针指向不同地址
c[0] = 1 // 没问题 指针指向同一地址
var a = 1
function f() {
// var有变量提升 相当于在函数开始阶段var a; 然后再原var a = 2的地方a = 2, 所以这里是undefined
console.log(1, a)
// b是全局 或者const b let b都没有变量提升 所以这里 error b is not defined
console.log(2, b)
var a = 2
b = 3
let c = 4
// 2 沿作用域链往上找 内部就找到了a=2
console.log(3, a)
}
// 函数还没执行 全部变量b还没定义 error
console.log(4, b)
f()
// 函数已经执行 找到全局变量b
console.log(5, b)
// 不能访问函数内部变量a 只能访问到全局作用域var a = 1 所以是1
console.log(6, a)
// c是函数内的局部作用域 访问不了 error
console.log(7, c)
函数内部可以通过链式作用域读取到外部全局变量,但是在函数外部无法读取函数内部的局部变量,为了从外部读取函数内部的局部变量,所以有了闭包。 闭包可以理解成"函数内return函数",他是将函数内部和函数外部连接起来的桥梁,通过这个return函数能够读取外层函数的局部变量。
function f1(){
var n = 1
return function f2(){
// 闭包的this指向是window
console.log(n, this)
}
}
// 通过f2从外部访问到了f1内部的局部变量n
f1()() // 1
闭包示例1
function box(){
var age = 100;
return function(){
age++;
return age;
}
}
var aaa = box(); //只执行一次box 得到执行结果box()后赋值给aaa 之后再也不执行了 这样age就不会再重置为100
alert(aaa()); //101 box执行结果box()就是function(){age++; return age;} 然后这个匿名函数自我执行
alert(aaa()); //102
alert(aaa()); //103
var aaa = box(); //如果再执行box 那age又被重置为100了 所以下面是101
alert(aaa()); //101
aaa = null; //运用闭包后 aaa让age常驻了内存 所以记得不用后 清空aaa 等待垃圾回收
闭包示例2
// 输出16 16 16,因为等console的时候 i已经是3+1=4了
function count1() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(() => {
return i * i
});
}
return arr;
}
var a1 = count1()
console.log(a1[0]())
console.log(a1[1]())
console.log(a1[2]())
// 闭包改写 创建i局部作用域 输出1 4 9
function count2() {
var arr = [];
for (var i=1; i<=3; i++) {
// 原函数匿名函数自我执行并传入i包装一层
arr.push(((n) => {
return () => {
return n * n
}
})(i));
}
return arr;
}
var a2 = count2()
console.log(a2[0]())
console.log(a2[1]())
console.log(a2[2]())
var s3 = 10;
//参数xx是引用 s3是普通类型存在栈内层中 xx重新赋值为13 原来的s3还是10 所以弹出10
function fn3(xx){
xx += 3;
}
fn3(s3);
console.log(s3);
var s4 = [1,2,3];
//参数xx是引用 把对象类型数组s4传进来后 xx数组和原s4数组指向同一片堆内存 xx变成[1,2,3,4] 所以s4也变成[1,2,3,4]
function fn4(xx){
xx.push(4);
}
fn4(s4);
console.log(s4);
function sum(num){
console.log(arguments)
if(num <= 1){
// 必须要有结束条件
return 1;
}else{
// 函数内部调用自身函数
return num * arguments.callee(num - 1);
}
}
console.log(sum(4)); //4*3*2*1 = 24
- js只有一个主线程,同时还有任务队列和事件循环
- 任务队列分为微任务(promise nextTick等)和宏任务(异步,setTimeout,事件等),任务添加到任务队列的时机如下:
- onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任务队列中。
- setTimeout 会由浏览器内核的 timer 模块来进行延时处理,当时间到达的时候,才会将回调函数添加到任务队列中。
- ajax 则会由浏览器内核的 network 模块来处理,在网络请求完成返回之后,才将回调添加到任务队列中。
- promise的then等执行到了就添加到任务队列中
- 事件循环:JS会创建一个类似于while (true)的循环,每执行一次循环都查看是否有待处理事件,如果有则取出相关事件及回调函数放入执行栈中由主线程执行
- 如果任务队列里同时有这微任务和宏任务优先执行微任务,
// setTimieout推宏任务到队列, promise then推微任务到队列
// 先执行主线程执行栈(同步代码) 输出2 3 6
// 然后执行队列里的任务,先执行微任务4 5,然后执行宏任务1
// 2 3 6 4 5 1
setTimeout(() => {
console.log(1)
}, 0)
console.log(2)
new Promise((reslove) => {
console.log(3)
reslove()
}).then(() => {
console.log(4)
})
new Promise((reslove) => {
reslove()
}).then(() => {
console.log(5)
})
console.log(6)
// 判断回文
function f1 (str) {
return str === str.split('').reverse().join('');
}
console.log(f1('abdba'));
// 数组去重
function f2 (arr) {
var obj = {};
var resArr = [];
for (var i = 0; i<arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = true;
resArr.push(arr[i]);
}
}
return resArr;
}
console.log(f2([1, 2, 2, 3, 3, 3, 4, 5, 6, 6]));
// 返回字符串中字符出现次数最多的那字符
function f3 (str) {
var obj = {};
for (var i = 0; i < str.length; i++) {
if (obj[str.charAt(i)]) {
obj[str.charAt(i)] += 1;
} else {
obj[str.charAt(i)] = 1;
}
}
var maxChar = '';
var maxValue = 1;
for (var k in obj) {
if (obj[k] > maxValue) {
maxChar = k;
maxValue = obj[k];
}
}
return maxChar;
}
console.log(f3('sfdddsdfsdfdsf'));
// 冒泡排序
function f4 (arr) {
var temp = '';
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
temp = arr [i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
console.log(f4([7, 8, 4, 3, 11, 12, 6]));
// 快速排序
function f5 (arr) {
if (arr.length <= 1) {
return arr;
}
var q = arr[0];
var leftArr = [];
var rightArr = [];
for (var i = 1; i<arr.length; i++) {
if (arr[i] < q) {
leftArr.push(arr[i]);
} else {
rightArr.push(arr[i]);
}
}
return [].concat(f5(leftArr), q, f5(rightArr));
}
console.log(f5([117, 8, 4, 3, 11, 12, 6]));
// 二分查找 找出有序数字指定数的index
function f6 (arr, key) {
var low = 0;
var high = arr.length;
while (low <= high) {
var mid = parseInt((low + high) / 2);
if (arr[mid] === key) {
return mid;
} else if (arr[mid] < key) {
low = mid + 1;
} else if (arr[mid] > key) {
high = mid - 1;
} else {
return -1;
}
}
}
console.log(f6([1, 3, 5, 7, 8, 12, 16], 12))
主要是跨域引起的
- cs架构,前后端分离,用HTTP通信
- 无状态不存储会话,每次请求带token(JWT)
- URL中只用名词不用动词,用POST(增加)、DELETE(删)、PUT(改)、GET(查)代替动词
- 用HTTP状态码返回当次执行结果
- 用HTTP header content-type指定json等格式
- 为集合提供分页排序筛选
- 提供版本号
- vue底层原理 250行mvvm系统
- react底层原理 state 更新机制
- 脚手架:升级到webpack5、加入ts选项、store及router分模块
- 组件库
- 性能及错误监控系统
- 性能优化、ssr