//值类型 let a = 200; let b = a; a = 100; console.log(a, b) // 引用类型 let a = { age: 24 }; let b = a; b.age = 25; console.log(a, b);
值类型
,值类型的复制就是复制栈里的value
。引用类型
的复制复制的是堆的引用内存地址
。css
值类型的占据内存比较小,引用类型占据的内存可能会很是大,不利于复制,从CPU和性能考虑把引用类型和值类型的复制的方式给分离出来。(js引擎)html
let a;// undefined const b = "string"; const c = false; const n = 100; const s = Symbol('s');
const obj = { age: 24 }; const arr = ["1", "2", "3"]; const n = null; // 特殊的引用类型,指针指向的是空地址 // 特殊引用类型 不用于存储数据,因此没有拷贝,复制函数之说 function fn() { }
全部的值类型,函数 引用类型只能到Object
重点1:初始化result
重点2:使用递归webpack
obj1 = { name: "胡子银", level: "p0" }; function deepClone(obj = {}) { if (typeof obj !== 'object' || typeof obj == null) { return obj; } // 初始化返回结果 let result; if (obj instanceof Array) { result = [] } else { result = {} } // 开始拷贝 for (let key in obj) { if (obj.hasOwnProperty(key)) { // 保证key 不是原型的属性 // 递归调用 result[key] = deepClone(obj[key]); } } return result; }
const a =100+10 // 110 const b = 100 +'10' // '10010' const c= true + '10' // 'true10'
100 == '100' // true 0 == '' // true 0 == false // true false =='' // true null == undefined // true
总结: 除了null
用 ==
其余都用===
ios
truely 变量与 falsely 变量 两次取反es6
类的继承:extends super 重写web
instanceof 是否是它构建的。父类。Object是全部的父类面试
Student.__proto__ === People.ProtoType // true
隐式原型 :Student.proto
显式原型:People.ProtoTypeajax
每一个class都有显式原型,每一个实例都有隐式原型,实例的隐式原型指向类的显式原型。json
instanceOfaxios
this 在不一样场景下,如何取值?
手写bind函数
闭包在实际开发场景中的应用
变量的合法使用范围。框里面的均可以。
做用域:
全局做用域
函数做用域
块级做用域 let const {}
做用域应用的特殊表现,有两种状况
函数
做为参数
被传递。函数
做为返回值
被返回。总之,函数定义的地方和执行的地方是不同的。
闭包:自由变量在函数定义的地方向上级做用域查找。而不是在执行的地方。
// 函数做为返回值 function createFun() { const a = 100; return function () { console.log(100); } } const fn = createFun(); const a = 200; fn();
// 函数做为参数被传递 const a = 100; function param() { console.log(a); }; function close(param) { const a = 200; param(); }; // const clo = new close(param); close(param);
函数在执行的时候决定。
箭头函数 ==> 取的是上级做用域的值
bind call 的区别
function fn() { console.log(this); } const fnbind = fn.bind({ x: 200 },10,20,30); fn(); fn.call({ x: 100 }); fnbind()
this的使用场景,console.log(this) 一、普通函数被调用 // window 二、做为对象方法 指向对象 三、bind,call,apply 把this的指向做为参数传递进去。(传进去的就是this) 四、箭头函数 this指向上一层做用域 五、在class中调用
JavaScript
中的Array.prototype.slice.call(arguments)
能将有length属性的对象转换为数组
Function.prototype.bind = function () { const args = Array.prototype.slice.call(arguments); // 获取数组的第一项 const t = args.shift(); //此处this是fn1.bind()中的fn1 const self = this; return function () { return self.apply(t, args); } }
闭包: 自由变量在函数定义的地方向上级做用域查找。而不是在执行的地方。
闭包隐藏数据,只提供api,闭包中的数据,被隐藏,不被外界访问。
建立缓存,set,get,调用get方法取到的变量是,而不是
let构成了块级做用域
const imgUrl = "0000"; function loadImg(src) { return new Promise((resolve, reject) => { const img = document.createElement('img'); img.onload = () => { return resolve(img); } img.onerror = () => { return reject(new Error("图片加载失败")); } img.src = img; }) } loadImg(url).then((img) => { console.log(img.width); return img; }).then((img) => { console.log(img.height); })
事件轮训,事件循环
js是单线程,异步要基于回调实现,event Loop就是根据异步回调的实现原理
call Stack:调用栈 用完就清空
web apis:如setTimeout dom bom等
callback queue:回调函数队列
event loop:
总结: 同步代码,一行一行放在Call Stack执行 遇到异步,会先“记录”下,等待时机(定时、网络请求等); 时机到了,就移到Callback Queue 如Call Stack为空(即同步代码执行完成)Event Loop开始工做 轮询查找Callback Queue,若有则移到Call Stack 执行 而后继续轮询查找
dom事件也是基于Event Loop。
then 正常返回resolved ,里面有报错则返回rejected
catch 正常返回resolved,里面有报错则返回rejected
总结: 三种状态,状态和表现 then和catch对状态的影响(重要) then和catch的链式调用(常考) 只要是没报错,就是resolved。
异步回调
promise也是基于回调。async-await完全消灭了回调。
- 执行async函数,返回的是Promise对象 - await至关于Promise的then (假如直接返回的数据,至关于 Promise.resolve(400)) - try...catch可捕获异常,代替了Promise的catch
仍是基于回调函数,仍是基于event Loop
for...in(以及forEach for)是常规的同步遍历 ????
for...of 经常使用于异步遍历?????
宏任务与微任务
为何微任务比宏任务的执行时间要早?
event Loop 与 DOM事件 渲染。js是单线程的。也就是说event Loop与Dom渲染共用同一个线程。
宏任务在DOM渲染后触发,如setTimeout();
微任务,在DOM渲染后,如setTimeout();
为何宏任务在DOM渲染后触发,微任务在DOM渲染前触发?
宏任务与微任务的根本区别
从event Loop解释为何微任务比宏任务的执行时间早。
微任务是浏览器规定的
宏任务是es6规定的
存放的地方不同。
总结:
JS = ECMA (ECMA262标准)+DOM(w3c) +BOM (w3c)
W3C规定web-api,css,html,网络请求的东西还挺多的。
document object model
const div1 = document.getElementById("app1"); // const div2 = document.getElementsByClassName("appclass"); const divList = document.getElementsByTagName("div"); // list const pList = document.querySelectorAll("p"); // console.log("div1:", div1); console.log("div2", div2); console.log("divList:", divList); console.log("pList:", pList); // property 形式 修改属性值 console.log(pList[1].style.width); console.log(pList[1]); // attribute 形式 修改属性 pList[1].setAttribute("data-name", "imook"); console.log(pList[1].getAttribute("data-name")); pList[1].setAttribute("style", "font-size:50px");
打印出来的结果对比,直接获取的dom节点,list的会有属性
const listNode = document.getElementById("app1"); const flagNode = document.createElement("ul"); for (let i = 0; i <= 5; i++) { const li = document.createElement("li"); li.innerHTML = "innerHtml"; flagNode.appendChild(li); }; listNode.appendChild(flagNode);
ua
// navigator console.log(navigator.userAgent); // ua检查方案 // screen console.log(screen.width); // location console.log(location.href); // 整个网址 console.log(location.host) // 域名 console.log(location.search); // console.log(location.hash); // 哈希 # console.log(location.pathname); // // history history.back(); history.forward();
通用的事件绑定函数
<button id="btn1">点击</button> <script> var btn = document.getElementById("btn1"); function bindEvent(ele, type, fn) { ele.addEventListener(type, fn); }; btn.bindEvent("click", e => { // 阻止默认行为 e.proventDefault(); // e.target console.log(e.target); console.log("事件绑定"); }) </script>
事件冒泡
事件代理
把事件绑定到父元素上,点击子元素,弹出子元素的interhtml
代码简洁,减小浏览器的内存使用,可是不要滥用。
GET
const xhr = new XMLHttpRequest(); xhr.open("GET", "./data.json", true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log(JSON.parse(xhr.responseText)); alert(xhr.responseText); } else { console.log(xhr.responseText); } } } xhr.send(null);
POST
const xhr = new XMLHttpRequest(); xhr.open("POST", "./login", true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log(JSON.parse(xhr.responseText)); alert(xhr.responseText); } else { console.log(xhr.responseText); } } } const postData = { "name": "狂徒张三" } xhr.send(JSON.stringify(postData));
301 永久重定向
302 临时重定向
304 资源有,重复,浏览器用本身的。事关性能优化
404 地址错了
403 没有权限
jsonp的主要内容有两点:
一、script能够跨域
二、服务器拿到url能够动态的返回一些内容
cors
是服务端设置请求头,容许哪些进行访问。
jqyery.ajax()
fetch()
axios
xmlhttprequest
题目:描述cookie localStorage sessionStorage 的区别
cookie的价值不在于本地存储,而在于与服务端的通讯。是被借用来做为本地存储的工具。因为每次请求都须要带着cookie,因此会增长请求的数据量,并且cookie的最大的存储空间是4kb,只能经过document.cookie来修改。过于简陋。 修改的方式:相同的key,覆盖,不一样的key,追加
localStorage数据会永久存储,除非代码或者手动删除 sessionStorage数据只存在于当前会话,当浏览器关闭就清空
常见的状态码:
301 永久重定向
302 临时重定向,
举例1:在百度检索了一个css教程,hover上去的连接点击之后,先是访问百度的url而后浏览器的location再跳转到真正的目的连接地址、。
举例2:还有短链
304:浏览器已经请求过了,可使用本地的,本地的没过时
403:没权限
404:地址错误
5 **:服务端
关于协议和规范:就是一个约定和规范
get
post
get 查
post 建立新的
patch
delete
尽可能不要使用参数,使用method做为类型
网络请求加载比较慢,cpu计算比较快。性能优化的主要瓶颈就在于网络请求,当部分不须要被重复请求的资源被缓存,就能够减小http请求,从而优化性能。
哪些资源能够被缓存?静态资源,(js,css,图片,与webpack打包加的hash有关,只有内容改变了,才会再次更改)
一、强制缓存
cache-contral 强制缓存,控制强制缓存的逻辑
cache-control:max-age=2592000 (秒)
max-age:过时时间 no-cache : 本地不作缓存 no-store:本地不缓存,服务器端也不缓存。
关于Expires
二、协商缓存(对比缓存)
Last-Modified: 最后一次修改的时间
Etag: 人类的指纹,惟一的标识,字符串
二者共存,会优先使用Etag,Etag会更加精准。
总结: 就是请求服务端,问问服务端本地的能不能用。
正常操做:url的前进后退; 都有效
手动刷新:强制缓存失效,协商缓存有效
强制缓存:contral + command + 2 都失效