标签:传输层 多公司 标签 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