疑惑知识点总结

216 阅读9分钟

跨域问题及解决

跨域是指浏览器的不执行其他网站脚本的,由于浏览器的同源策略造成,是对JavaScript的一种安全限制, 当你通过浏览器向其他服务器发送请求时,不是服务器不响应,而是服务器返回的结果被浏览器限制了。同源策略是必须的,否则cookie可以共享。

解决办法

  1. jsonp: JSONP是服务器无客户端跨源通信的常用方法。基本思想是网页通过添加一个
  2. 代理服务器: 使用代理方式跨域更加直接,因为同源限制是浏览器实现的。如果请求不是从浏览器发起的,就不存在跨域问题了
  3. cors: 跨域资源共享(corss-origin resource sharing):CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

js中解构

  1. 默认赋值 给解构的变量赋予默认值, 就是说当age, 没有值
const User = {
  name: '111',
}
const { name, age=18 } = User; //name=111 ; age=18

  1. ...展开式 这里的...会将后面的变量rest 变为一个对象, 用对象来接收余下的所有变量 ; c : d 是将变量c 更改名字为d
const obj = { a: 1, b: 2, c: 3, d: 4 };
const {
 a,       // a = 1
 c: d,      // d = 3
 ...rest     // rest = { b: 2, d: 4 }
} = obj;
const nested = { a: { b: 1, c: 2 }, d: [1, 2]};
const {
 a: {
  b: f,     // f = 1
  ...g     // g = { c: 2 }
 },
 ...h      // h = { d: [1, 2]}
} = nested;
  1. 通过解构对象中的数字代表数组中下标对应的值; length 能拿到数组的长度并改名为count; 增添一个新的变量name; 用restData 接收所有未直接解构的变量
const arr = [ 5, 'b', 4, 'd', 'e', 'f', 2 ];
const {
 6: x,      // x = 2
 0: y,      // y = 5
 2: z,      // z = 4
 length: count, // count = 7
 name = 'array', // name = 'array' (not present in arr)
 ...restData   // restData = { '1': 'b', '3': 'd', '4': 'e', '5': 'f' }
} = arr;
  1. 数组解构中的...赋值 这里展开后的rest为一个数组 (也就是说...如果用在对象中, 后面的变量就为一个对象, 如果用在数组中, 后面的变量就为一个数组)
[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest); //[30, 40, 50]
  1. 交换两个变量的值
let a = 1;
let b = 3;
//交换a和b的值
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

  1. 改名并赋予默认值
let { a: aa = 10, b: bb = 5 } = { a: 3 };
console.log(aa); // 3
console.log(bb); // 5

动态路由传参

通过params 或 query 传参, 其中name 配合params 能在<router-link中使用> ; params传参不能用path,只能用name, 并且通过params 传值在浏览器地址栏中不显示参数, 更加安全

CSDN: blog.csdn.net/Lemontree_f…

观察者模式和订阅者模式

观察者模式

定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新

image.png

订阅者模式

发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在

image.png

区别

image.png

  1. 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
  2. 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
  3. 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

数据处理

数组的拷贝

这些方式能够拷贝新数组并且不拷贝原数组的地址

// `arr` is an array
const clone = arr => arr.slice(0);

// Or
const clone = arr => [...arr];

// Or
const clone = arr => Array.from(arr);

// Or
const clone = arr => arr.map(x => x);

// Or
const clone = arr => JSON.parse(JSON.stringify(arr));

// Or
const clone = arr => arr.concat([]);

对象的合并 (Object.assign)

注意这个方法会将两个对象中相同键的部分进行覆盖处理, 以方法中最后一个为准

let aaa = {
 text: 2,
 value: 11,
}

let bbb = {
  text: 3
}

let ccc = Object.assign(aaa,bbb) // aaa目标对象, bbb源对象

console.log(ccc) // { text:2, value:11 }

call、apply、bind的用法和区别

这里案例中的this 都指向obj, 但如果我要显示的是db 中的数据的话, 就需要将this 指向db, 同时还要注意bind 指向之后需要手动调用, 而call 和bind 能够自动执行

image.png

obj.myFun.call(db);    // 德玛年龄 99
obj.myFun.apply(db);    // 德玛年龄 99
obj.myFun.bind(db)();   // 德玛年龄 99

注意

  • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
  • bind 是返回绑定this之后的函数,便于稍后调用;apply 、call 则是立即执行
  • apply 可以接收伪数组, 也就是说这种情况也可以
func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// func 接收到的参数实际上是 1,2,3

平铺结构数据转树形结构

用数组方法实现

export function tranListToTreeData(list) {

// 1. 定义两个变量

const treeList = []; const map = {}



// 2. 建立一个映射关系,并给每个元素补充children属性.

// 映射关系: 目的是让我们能通过id快速找到对应的元素

// 补充children:让后边的计算更方便

list.forEach(item => {

if (!item.children) {

item.children = []

}

map[item.id] = item

})


// 循环

list.forEach(item => {

// 对于每一个元素来说,先找它的上级

// 如果能找到,说明它有上级,则要把它添加到上级的children中去

// 如果找不到,说明它没有上级,直接添加到 treeList

const parent = map[item.pid]

// 如果存在上级则表示item不是最顶层的数据

if (parent) {

parent.children.push(item)

} else {

// 如果不存在上级 则是顶层数据,直接添加

treeList.push(item)

}

})

// 返回

return treeList

}

用递归实现

这里的递归退出条件为, 数组为空的时候, 就不会继续进入到函数调用的递归代码

image.png

promise 面试题

红色框为同步代码, 绿色框为异步代码

image.png

image.png

image.png

注意

  1. await axios() 返回值 和 后面的代码为异步代码, 而调用函数为同步代码

image.png

  1. 实际上是宏任务和宏任务的队列, 其中每个宏任务后面都排有微任务 (单个宏任务完成之后, 再进行内部的微任务, 再进行下一个宏任务)

image.png

浏览器代码审查

image.png

  1. 不进入调用函数中的代码, 直接拿到函数调用的结果
  2. 进入函数中的代码, 而不是直接拿到函数调用的结果
  3. 监视器, 可以将需要监视的变量放到监视器中, 实时显示变化的值
  4. 不同作用域中的变量
  5. 函数回调栈, 其中script 标签为一级匿名函数
  6. 栈队列为先进后出, 所以需要一级一级完成才能结束代码

tcp 与 udp 传输协议

tcp 与 udp.png

  1. 当数据不太重要, 数据暂时丢失不太重要的场合, 就可以用udp, 比如视频直播的时候, 卡顿时的数据丢失也没关系, 但像王者中卡顿之后, 数据还是会全部加载, 用的就是tcp 连接

数据类型检测

适用于返回
typeof基本数据类型string
instanceof任意对象true/false
Object.prototype.toString基本数据类型、内置对象以及包含 Symbol.toStringTag 属性的对象string

闭包注意点

  • 使用闭包的注意点:  由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除(引用设置为 null ,这样就解除了对这个变量的引用,其引用计数也会减少,从而确保其内存可以在适当的时机回收)
  • 内存泄漏:  程序的运行需要内存。对于持续运行的服务进程,必须及时释放不再用到的内存,否则占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏
  • this指向:  闭包的this指向的是window

call 的应用

  1. 这里的 this 指向的是 obj, 同时向函数 foo 中传递两个参数, a和b 能拿到这两个参数
var obj = {name: "李四", age: 20};
function foo(a, b){
    document.writeln(this.name);    
    document.writeln(a);    
    document.writeln(b);    
}
// 改变this引用为obj,同时传递两个参数
foo.call(obj, 12, true); // 李四 12 true

Array.prototype.slice.call(arguments,0)这句里,就是把 arguments 当做当前对象, 也就是说 要调用的是 arguments 的 slice 方法,后面的 参数 0 也就成了 slice 的第一个参数,slice(0)就是获取所有。

  1. [].slice.call(arguments)能将具有length属性的对象转成数组
  • Array.prototype.slice.call(伪数组) 也能将伪数组转成真数组

nextTick 原理 (待补充)

nextTick 原理.png

@hook 钩子函数

能够在父组件中使用, 能够在子组件通过 @hook 绑定生命周期函数, 根据子组件的生命周期不同时机执行不同函数(也就是说这里的 @hook:mounted 会在子组件的 dom 加载完成后执行函数)

<v-chart
    @hook:mounted="loading = false"
    @hook:beforeUpdated="loading = true"
    @hook:updated="loading = false"
    :data="data"
/>

实例属性 / 原型属性 / 静态属性 的区别

image.png

这个案例解释了 vue 的 data 为什么要是一个函数的问题

为了形成局部作用域, 使不同组件的相同名字的变量不会相互影响, 因为 data 返回的对象会开辟一个新的内存空间

image.png

小的注意点

  1. 注意数据的原型的数据类型不只有对象一种

image.png

补充点

  1. 通过给元素标签设置 id, 能够通过 js 代码直接通过 id 拿到元素 (不过版本浏览器不兼容)