标签:传输层 多公司 标签 dev 计算机网络体系结构 javascrip prevent load 无法
1. 区别 == 和 ===
== 比较的是两个变量的值
=== 比较两个变量的 类型 和 值
基本数据类型(undefined,boolean,number,string,null)
存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。
基本数据类型的比较是值的比较
引用数据类型(object)
放在堆中,其引用就是内存地址
引用类型的比较是引用的比较
2. 浅拷贝 和 深拷贝
(拿一个对象来说,当然也可以是数组。非基本类型的拷贝,才会有深拷贝、浅拷贝的区别)
(1)仅仅拷贝变量(变量的赋值)
var obj1 = {
‘name‘ : ‘zhangsan‘,
‘age‘ : ‘18‘,
‘arr‘ : [1,[2,3],[4,5]],
};
var obj2 = obj1;
(2)一层拷贝
function shallowCopy(src) { // 一层浅拷贝
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
/**** test ****/
var obj = {
a:1,
arr: [2,3]
};
var shallowObj = shallowCopy(obj);
造成的坏处就是:obj.arr[0] = 0; console.log(shallowObj.arr[0]); // obj 的里 arr 的改变,会影响到 shallowObj.arr
let a = {
name: "muyiy",
book: {
title: "You Don‘t Know JS",
price: "45"
}
}
let b = Object.assign({}, a); // 将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
a.name = "change";
a.book.price = "55";
console.log(a.name, ‘\n ---- \n‘, b.name); // 第一层的基础类型不会互相影响
console.log(a.book, ‘\n ---- \n‘, b.book); // 但是第一层的复杂数据类型,即第二层 互相影响了
let a = {
name: "muyiy",
book: {
title: "You Don‘t Know JS",
price: "45"
}
}
let b = {...a};// 将所有可枚举属性展开,放到一个新对象中
a.name = "change";
a.book.price = "55";
console.log(a, ‘\n ---- \n‘, b);
console.log(a.book, ‘\n ---- \n‘, b.book);
会发现 和 Object.assign() 的效果一模一样。只是实现了第一层的拷贝,第二层更深层 会互相影响
完全改变变量 a 之后对 b 没有任何影响,这就是深拷贝的魔力
(1)const b = JSON.parse(JSON.stringify(a));
原理:
缺点:
let obj = {
a: 1,
b: {
c: 2,
d: 3
}
}
obj.a = obj.b;
obj.b.c = obj.a;
let b = JSON.parse(JSON.stringify(obj));
// Uncaught TypeError: Converting circular structure to JSON
// 木易杨 new Date(); // Mon Dec 24 2018 10:59:14 GMT+0800 (China Standard Time) JSON.stringify(new Date()); // ""2018-12-24T02:59:25.776Z"" JSON.parse(JSON.stringify(new Date())); // "2018-12-24T02:59:41.523Z"
解决方法转成字符串或者时间戳就好了。
// 木易杨 let date = (new Date()).valueOf(); // 1545620645915 JSON.stringify(date); // "1545620673267" JSON.parse(JSON.stringify(date)); // 1545620658688
// 木易杨
let obj = {
name: "muyiy",
a: /‘123‘/
}
console.log(obj);
// {name: "muyiy", a: /‘123‘/}
let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "muyiy", a: {}}
(2)三方库 jQuery.extend().
(3)原生三方库 lodash.cloneDeep()
var objects = [{ ‘a‘: 1 }, { ‘b‘: 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); // => false
(4)自己写 思路就是递归调用刚刚的浅拷贝,把所有属于对象的属性类型 都遍历赋给另一个对象即可
// 内部方法:用户合并一个或多个对象到第一个对象
// 参数:
// target 目标对象 对象都合并到target里
// source 合并对象
// deep 是否执行深度合并
function extend(target, source, deep) {
for (key in source)
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
// source[key] 是对象,而 target[key] 不是对象, 则 target[key] = {} 初始化一下,否则递归会出错的
if (isPlainObject(source[key]) && !isPlainObject(target[key]))
target[key] = {}
// source[key] 是数组,而 target[key] 不是数组,则 target[key] = [] 初始化一下,否则递归会出错的
if (isArray(source[key]) && !isArray(target[key]))
target[key] = []
// 执行递归
extend(target[key], source[key], deep)
}
// 不满足以上条件,说明 source[key] 是一般的值类型,直接赋值给 target 就是了
else if (source[key] !== undefined) target[key] = source[key]
}
// Copy all but undefined properties from one or more
// objects to the `target` object.
$.extend = function(target){
var deep, args = slice.call(arguments, 1);
//第一个参数为boolean值时,表示是否深度合并
if (typeof target == ‘boolean‘) {
deep = target;
//target取第二个参数
target = args.shift()
}
// 遍历后面的参数,都合并到target上
args.forEach(function(arg){ extend(target, arg, deep) })
return target
}
以上是 Zepto 中深拷贝的代码
3. 如何合并两个对象
const obj1 = {a: 0, b: 1, c: 2};
const obj2 = {c: 3, d: 4, e: 5};
const obj = {...obj1, ...obj2};
// obj => {a: 0, b: 1, c: 3, d: 4, e: 5}
// 创建一个新的对象,遍历需要克隆的对象,将需要克隆对象的属性依次添加到新对象上,返回
function clone(target) { let cloneTarget = {}; for (const key in target) { cloneTarget[key] = target[key]; } return cloneTarget; };
function clone(target) {
if (typeof target === ‘object‘) { // 只考虑了普通的 object
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = clone(target[key]);
}
return cloneTarget;
} else {
return target;
}
};
const oldObject = {
field1: 1,
field2: undefined,
field3: ‘ConardLi‘,
field4: {
child: ‘child‘,
child2: {
child2: ‘child2‘
}
}
};
const newObject = clone(oldObject);
console.log(newObject);

这个基础版本,还有很多不足,比如,还没有考虑数组
module.exports = function clone(target) {
if (typeof target === ‘object‘) {
let cloneTarget = Array.isArray(target) ? [] : {};
for (const key in target) {
cloneTarget[key] = clone(target[key]);
}
return cloneTarget;
} else {
return target;
}
};
/**** test ****/
const oldOne = {
field1: 1,
field2: undefined,
field3: {
child: ‘child‘
},
field4: [2, 4, 8]
};
const newOne = clone(oldOne);
console.log(newOne);

解决循环引用问题:
我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系
当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝
这样就巧妙化解的循环引用的问题
这个存储空间,需要可以存储 key-value 形式的数据,且 key 可以是一个引用类型,我们可以选择 Map 这种数据结构
map中有无克隆过的对象key,克隆对象作为value进行存储function clone(target, map = new Map()) {
if (typeof target === ‘object‘) {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
cloneTarget[key] = clone(target[key], map);
}
return cloneTarget;
} else {
return target;
}
};
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。
什么是弱引用呢?
在计算机程序设计中,弱引用与强引用相对,是指不能确保其引用的对象不会被垃圾回收器回收的引用。
一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。
4. 改变对象的一个属性
例如 const a = {index: 1, name: ‘kjf‘};
需要把 index 改成 2
a = {...a, index: 2};
5. react 数据流 以及 vue 数据流
都是组件化编程
每个组件都有自己的 state 状态
react 的 state 发生变化 会触发重新 render 渲染组件
vue 的 state 发生变化 会尽量少的 页面渲染,先是在内存的虚拟dom 进行逻辑处理,然后批量的更新组件
6. 原型链
每个函数都有一个 prototype 显示原型属性 ---- 原型对象
每个实例对象都有一个 __proto__ 隐式原型属性 ---- 指向其构造函数的原型对象
对象找属性时,会先在自身查找
如果没有 就沿着 __proto__属性一层一层的向上查找
直到查找到 Object.prototype.__proto__ === null 如果还没找到,就是 undefined

7. 计算机网络体系结构分几层、http 在哪一层
计算机网络体系结构分层: (有两种常见的模型)
ing
应用层: HTTP、DNS、Telnet、FTP、SNMP、SMTP、TFTP
传输层: TCP/UDP
网络层: IP
数据链路层
物理层
8. 前后端联调 RESTful API,请求类型、作用以及区别
参考: https://www.cnblogs.com/tianxiaxuange/p/13324857.html
9. Object.defineProperty() 劫持属性的缺点,vue3 是如何解决的
参考: https://juejin.im/post/5bf3e632e51d452baa5f7375
所以 vue 提供了 hack 处理过的八种方法 push()、pop()、shift()、unshift()、splice()、sort()、reverse()方法修改数组,可以触发渲染页面
this.$delete(target, propertyName/index) 避开 Vue 不能检测到 property 被删除的限制
this.$set( target, propertyName/index, value ) 向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新
Proxy代理目标对象,是通过操作上面的13种trap来完成的
// p 是代理后的对象。当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法
// target 是用Proxy包装的被代理对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
// handler 是一个对象,其声明了代理target 的一些操作,其属性是当执行一个操作时定义代理的行为的函数
// hander 是一个对象包含4个方法 {
get:读取
set:修改
has:判断对象是否有该属性
construct:构造函数
}
let p = new Proxy(target, handler);
let obj = {};
let handler = {
get(target, property) {
console.log(`${property} 被读取`);
return property in target ? target[property] : 3;
},
set(target, property, value) {
console.log(`${property} 被设置为 ${value}`);
target[property] = value;
}
}
let p = new Proxy(obj, handler);
p.name = ‘tom‘ //name 被设置为 tom
p.age; //age 被读取 3
10. 前后端分离 与 前后端不分离 的区别
所以类似于京东,淘宝这些网站,首屏数据一般都是由服务器端渲染的
后期通过JS添加到页面中的内容,并不会写在页面的源代码中(是源代码不是页面结构)
浏览器再把动态增加的部分重新渲染,无形中浪费了一些时间,没有服务器端渲染页面呈现速度快
11. vue seo 以及 vue 性能优化
https://juejin.im/post/5f0f1a045188252e415f642c
(1)v-for 的优先级其实是比 v-if 高的
(2)v-for 尽量不使用 index 去作为 key,而是使用唯一值如 id
(3)及时释放资源,如 setInterval
(4)路由懒加载(使得 Vue 服务在第一次加载时的压力就能够相应的小一些)
// require法 component: resolve=>(require([‘@/components/HelloWorld‘], resolve)) // import component: () => import(‘@/components/HelloWorld‘)
(5)webpack 处理打包的 JavaScript 文件,图片文件
(6)使用 Tree-Shaking 插件可以将一些无用的沉淀泥沙代码给清理掉
(7)使用CDN的方式引入一些依赖包,在正式环境下,通过CDN,确实有了一些明显的提升
(1)控制首页链接数量(不宜过多,也不宜过少)
(2)扁平化的目录层次(尽量让“蜘蛛爬虫”只要跳转3次,就能到达网站内的任何一个内页)
(3)导航优化 <img> 标签必须添加 “alt” 和 “title” 属性,告诉搜索引擎导航的定位,做到即使图片未能正常显示时,用户也能看到提示文字
<a>标签:页内链接,要加 “title” 属性加以说明,让访客和 “蜘蛛” 知道。
而外部链接,链接到其他网站的,则需要加上 el="nofollow" 属性, 告诉 “蜘蛛” 不要爬,因为一旦“蜘蛛”爬了外部链接之后,就不会再回来了
(4)良好的网站的结构布局,头部、主体(正文、热门)、底部
(5)突出重要内容---合理的设计title、<meta description>和 <meta keywords>
(6)语义化书写 HTML 代码,符合 W3C 标准
h1-h6 是用于标题类的
<nav> 标签是用来设置页面主导航
列表形式的代码使用 ul 或 ol
重要的文字使用 strong 等
(7)h1标签自带权重“蜘蛛” 认为它最重要,一个页面有且最多只能有一个H1标签,放在该页面最重要的标题上面
如首页的 logo 上可以加 H1 标签。副标题用 <h2> 标签, 而其它地方不应该随便乱用 h 标题标签
(8)
(9)
13. 源码解读及收获
(1)闭包结构封装:
jQuery 具体的实现,都被包含在了一个立即执行函数构造的闭包里面,为了不污染全局作用域,只在后面暴露 $ 和 jQuery 这 2 个变量给外界,尽量的避开变量冲突
根据函数作用域链,若没有传入window,就会一层一层向上查找window,而window对象是最顶层的对象,查找速度就会非常慢,传入后,只需要查找参数即可。
(3)jQuery 无 new 构造?
因为封装在了里面,jQuery 里面进行了 new 实例化
(4)链式调用(对象的方法,返回值还是这个对象)
()
1
1
14. typescript 的功能及优势
(1) 学习路线
(2)发展:
TypeScript 是 2012 年由 Microsoft 推出的一门工具
(3)功能:
/** * 方法:foo * @param {string} name */ function foo (name) { console.log(name) return name }
/**
* 方法:foo
* @param {{firstname: string, nameLength: number}} name
*/
function foo (name) {
console.log(name)
return name
}
这时函数内的 name 就不是一个string了,而是一个自定义的object类型。当然,当我们访问 name 时,会得到 firstname 和 nameLength 两个属性
/**
* ajax方法
*
* @example `ajax(‘url‘, options)`
*
* @typedef {Object} IAjaxOptions
* @property {boolean} [jsonp] 是否jsonp
* @property {boolean} [async] 是否async
* @property {‘GET‘|‘POST‘} [methods] 请求方法
* @property {(options: any)=>void} [success] 成功回调函数
*
* @param {string} url url
* @param {IAjaxOptions} [options] 参数
* @param { Promise }
*/
function ajaxNew (url, options) {}
其中 @typedef 的效果是声明一个 type 类型(或者理解为将一个类型起个别名),比如这里就是object类型,名为IAjaxOptions。 而@property的作用是声明上面类型里面包含的属性,用法和@param一致
(4)优势:
15. redux-observable 和 RxJS
RxJS 是用 typescript 编写的
Angular 重度使用了 RxJS
标签:传输层 多公司 标签 dev 计算机网络体系结构 javascrip prevent load 无法
原文地址:https://www.cnblogs.com/mailyuan/p/13381792.html