@anoninz
2020-01-16T07:33:27.000000Z
字数 16658
阅读 663
Q 想了解一下这个岗位的发展如何
Q 公司的培训体系如何
未解决
// 原型链的构建
// REST(Representational State Transfer) 可重新表达的状态迁移
// RESTful API
// 六个具体约束:
// 1. 通信只能由客户端发后面发起,表现为请求-相应的形式
// 2. 无状态: 通信的会话状态应该有客户端负责维护
// 3. 缓存:相应内容可以在通信链的某处被缓存,以改善网络效率
// 4. 统一接口:通信连的组件之间通过统一的接口相互通信,以提高交互的可见性
// 5. 分层系统:通过限制组件的行为(即每个组件只能看到与其交互的相邻层),将架构分解为若干等级的层
// 6. 按需代码:支持通过下载并执行一些代码,对客户端的功能进行扩展
localStorage 本地存储,长期存在,大小一般为 10Mb,同源策略,因此可以用来跨页面交互数据
sessionStorage 同上,但关闭浏览器就会消失
Storage.length // 返回一个整数,数据项数量
Storage.setItem(key, value) // 储存 / 更新Storage.getItem(key) // 读取Storage.removeItem(key) // 删除Storage.clear() // 清空
cookies
cookie,持久 cookie,持久 cookie 可以设置过期时间Expires或者有效期Max-Agedomain、路径path(子路径可用) secure标记https协议传输
document.cookie = "yummy_cookie=choco"document.cookie = "tasty_cookie=strawberry"console.log(document.cookie)
key来模拟一系列表单控件XMLHttpRequest的send()方法来异步提交表单ajax相比, FormData最大的优点就是可以异步上传一个二进制文件
var formData = new FormData(form)formData.append('username', 'Chris');// 在 html 中 name 是必须的<form id="myForm" name="myForm"><div><label for="username">Enter name:</label><input type="text" id="username" name="username"></div><div><label for="useracc">Enter account number:</label><input type="text" id="useracc" name="useracc"></div><div><label for="userfile">Upload file:</label><input type="file" id="userfile" name="userfile"></div><input type="submit" value="Submit!"></form>var myForm = document.getElementById('myForm')formData = new FormData(myForm)
File 对象一般来自于input元素上,选择文件之后返回的FileList对象DataTransfer对象HTMLCanvasElement mozGetAsFile() 方法File对象是特殊类型的Blob,可以在 XMLHttpRequest.send()中处理
File.lastModified // 最后修改时间File.lastModifiedDate // 最后修改时间的 Date 对象File.name // File 引用文件的名字File.size // 文件大小File.path // path 或者 UrlFile.type // 文件扩展类型
在层叠上下文中,其子元素同样也按照上面解释的规则进行层叠。特别值得一提的是,其子元素的 z-index 值只在父级层叠上下文中有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。
<div style="float:left;width:200px;"></div><div style="margin-left: 200px;"></div>
<div style="float:left;width:200px;"></div><div style="float:right;width:200px;"></div><div style="margin-left: 200px;margin-right: 200px;"></div>
son {width: 200px;margin: 0 auto;}
father {display:table-cell;text-align:center;vertical-align:middle;}son {display: inline-block;vertical-align: middle;}
father {display: flex;justity-content: center;}
father {position: relative}son {position: absoluteleft: 50%;trnasform: translateX(-50%;)}
div {line-height: 30px;height: 30px;}
- 相邻的两个块级元素,间距是两者 margin 的最大值
- 父子两个块级元素: 若第一个子元素的 top 上没有 border padding ,上方没有 inlineBlock 清除浮动的话,那么父子两元素的 margin 将合并,取两者的max
- 标准 content-box width 只是 content 部分
- 怪异 border-box width 包含 margin+padding+border+content 部分
div {transition: 1s 1s height ease, 1s 1s width ease;}// 可以通过增减 class 设置 transform 效果// 持续时间 延迟时间 方向/属性 弹性效果div {animation: 1s 1s rainbow linear 3 forwards normal;}// 持续时间 延迟时间 动画名称 时间线性弹性 循环次数(infinite) 播放方向@keyframes rainbow {0% { background: #c00; }50% { background: orange; }100% { background: yellowgreen; }}
var a = {v: 1}var b = aconsole.log(b.v) // 1a.v = 2console.log(b.v) // 2a = {v: 3}console.log(b.v) // 2 b指向了 a 之前的对象,重置了 a,b 的指向没有变化
console.log(a) // undefinedvar a = 1// 相当于// var a// console.log(a)// a = 1
console.log(b()) // 2 变量提升了function b() {return 2}
console.log(c()) // c is not a functionvar c = function() {return 3}// 相当于// var c// console.log(c())// c = function() {return 3}
console.log(d)let d = 4
var x = 0function test() {console.log(this.x)}var o = {}o.x = 1o.m = testo.m.apply() // 0 apply 需要指定一个 this,null 或者 undefined 则指向了 window 所以是 0o.m() // 1 谁调用,指向谁
var foo = {bar: function() {return this.baz},baz: 1,}(function() {return typeof arguments[0]()})(foo.bar)
call和apply都可以改变一个函数调用的环境(不改变原来的this),并立即调用call后面可以跟更多用逗号分隔开的参数apply的第二个参数必须是一个数组this和参数的函数,这个函数可以稍后调用
const log = console.log.bind(console)
function Foo() {this.name = 'a'}var f1 = new Foo()f1.name = 'b'console.log(f1.name) // 'b'var f2 = new Foo()console.log(f2.name) // 'a'
继承时,JavaScript 只有一种结构:对象。每个对象都有一个私有属性(称之为 [[Prototype]]),它持有一个连接到另一个称为其 prototype 对象(原型对象)的链接。该 prototype 对象又具有一个自己的原型,层层向上直到一个对象的原型为 null。(译者注:Object.getPrototypeOf(Object.prototype) === null; // true)根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
function Foo() {this.name = 'a'}Foo.prototype.logName = function() {console.log('name is', this.name)}var f1 = new Foo()f1.logName() // name is a 没有修改原型 Foo 的 namevar f2 = new Foo()f2.logName = function() {console.log('name')}f2.logName() // name 覆盖了 原型链上的 logName() 函数var f3 = new Foo()f3.name = 'c'f3.logName() // name is c 只覆盖了 Foo 上的 name
(function() {return typeof arguments})()
setInterval 是每过一段时间之后执行 function,清除用 clearInterval(id) 的方法
setTimeout 与循环结合
for (var i = 0; i < 5; i++) {setTimeout(function() {console.log(new Date(), i)}, 1000)}console.log(new Date(), i)// 00:00:00 5// 00:00:01 5// 00:00:01 5// 00:00:01 5// 00:00:01 5// 00:00:01 5
// 讲清楚这三个概念
addEventListener(event, callback, useCapture)
var bibao = function() {var i = 0var addI = function() {i++return i}return addI}var a = bibao() // 这个 a 就是闭包// 改写一下var a = (function() {var i = 0return function() {i++return i}})()
// 实现 deepClone 函数,JSONJSON.parse(JSON.stringify(obj)) // 一般业务数据够用了// 或者用 jQueryvar newObject = jQuery.extend(true, {}, oldObject);//lodash 的_.clone(true, obj)// 浅复制数组var a = b.slice()var a = b.concat([])
var ajax = function(method, path, data, responseCallback) {var r = new XMLHttpRequest()// 设置请求方法和请求地址r.open(method, path, true)// 设置发送的数据的格式r.setRequestHeader('Content-Type', 'application/json')// 注册响应函数r.onreadystatechange = function() {if(r.readyState === 4) {responseCallback(r)}}// 发送请求r.send(data)}// 0 1 2 3 4 各代表什么含义// 0 代理被创建,但并未 open()// 1 已经调用 open()// 2 已经调用 send() 并且头部和状态已经获得了// 3 正在下载// 4 下载完成
跨域有哪些常见的解决方式
网络安全: xss, csrf
script元素,浏览器会识别为js代码,如果这个代码有访问外部服务器,就是 xss 攻击// DOM 查找/添加/删除/修改对应的 API 是什么
// 新建document.createElement('div') // 创建节点document.createTextNode('我是新增的文本节点') // 创建文本节点document.querySelector('#div1').cloneNode(true) // true 深度克隆一个节点// 修改parent.appendChild(child) // 在 parent 最后位置插入 childa.insertBefore(b,c) // 在 a 的 c 元素之前插入 b,若 c 不存在会插入在最后a.insertAdjacentHTML('beforebegin', b) // 在 a 的第一个子元素之前加入 afterbegin beforeend afterend// 删除a.removeChild(b) 删除 a 中的 b 并返回 b 这个 domparent.replaceChild(newNode,oldNode)// 设置a.setAttribute(prop, value) 给 a 元素的 prop 元素设值 valuea.innerHTML 获取/设置 doma.innerText 获取文本a.value 获取/设置 input/select 的值// 查找document.querySelector('.test')document.querySelectorAll('.test')[0]element.childNodes // 子节点element.parentNode // 子节点ele.previousElementSibling 前一个节点ele.nextElementSibling 后一个节点closet(query) 可以用递归实现// 监听事件addEventListener('type', 函数名称, true/false) // 事件类型 回调函数 是否有捕获removeEventListener('type', 函数名称)
jQuery 常见 Apihttp://www.jianshu.com/p/8a26e66254ed
Array.length // 数组长度Array.prototype //数组原型
Array.from(a) // 从类数组或迭代对象中创建一个新的数组实例Array.isArray(a) // 判断 a 是否是数组// 改变原数组的方法arr.push(b) // 尾部增加 b,并返回新数组长度arr.pop() // 尾部删除并返回删除的元素arr.unshift(b,c) // 头部增加 b,c 并返回新 lengtharr.shift() // 删除第一个元素,并返回该元素arr.reverse() // 数组倒序排列arr.sort((a,b)=>{return Number} //按照比较两个元素,最后根据返回值排序//返回值 <0 a,b >0 b,a =0 保持原顺序arr.splice(index, num, a,b,c) // 在 index 位置开始删除 num 个元素,并用后续参数代替// 不改变原数组,但返回值为期望值arr1.concat(arr2) // 返回 arr1 后续 arr2 的数组arr.inculudes(b) // 返回布尔值,arr是否包含 b 元素arr.join(str=',') // 返回一个用 str 分隔开的 字符串arr.slice(index1, index2) // 返回 arr 从 index1 开始,到 index2 前一个元素的数组arr.indexof(b) // 返回第一个等于 b 的元素的 index,若不含有则返回 -1arr.lastIndexof(b) // 返回倒数第一个等于 b 的元素的 index,不含有则返回 -1// 遍历方法arr.forEach((item, index)=> {console.log(item, index)}) // 为arr 的每个元素执行一次函数,改变原数组arr.map((item, index)=>{return}) // 返回每个回调函数的返回值组成的数组arr.every((item)=>{return Boolean}) // 函数遍历每个元素返回值为 true,返回 true 否则 falsearr.some((item)=>{return Boolean}) // 函数遍历每个元素,返回值有一个 true ,则返回 true 否则 falsearr.find((item)=>{return Boolean}) // 函数遍历每个元素,返回值为 true 的元素,会被返回,否则 undefinedarr.findIndex((item)=>{return Boolean}) // 函数遍历每个元素,返回值为 true 的元素的 index 会被返回,否则 -1
var arr2 = arr1.slice() // 浅复制一个数组
// 有这样一个 url: http://vip.qq.com/a.php?a=1&b=2&c=3&d=xxx&e// 写一段 JS 程序将 url 的参数转成对象的形式{a: 1,b: 2,c: 3,d: 'xxx',e: '',}
var test = function(a,b, ...args) {// 参数 a b 可以直接用// args = [c,d,e ……]// 一个真实的数组}
promise.then((res)=>{}).catch((err)=>{}).done().finally()// Promise.all() 将多个 Promise 实例打包成新的 Promise,当所有都resolved 才回 resolved// 有一个 Promise 变成 rejected 则会变成 rejectedvar p1 = new Promisevar p2 = new Promisevar p = Promise.all([p1,p2])// Promise.race([p1,p2,p3]) 返回值是第一个发生改变的 promise 的返回值// Promise.resolve(res) 返回一个返回值是 res,且 resolved 的 Promise 实例// Promise.reject() 返回一个 reject 的 Promise 实例// 一个实际面试题,不过谁这么写代码我抽谁// 判断输出结果const a = (time) => {return new Promise((resolve, reject) => {setTimeout(() => {resolve('hhh')}, time)setTimeout(() => {reject('gua')}, 1000)})}a(500).then((res) => {console.log(res)}, (err) => {console.log(err)}).then((res) => {console.log(res, 2)}, (err) => {console.log(err, 2)}).catch((res) => {console.log('catch', res)})// 两个 then 会先后执行,第一个 then 可以拿到 res,第二个 then 拿不到// 因为没有抛出的错误,所以 catch 拿不到任何信息a(1200).then((res) => {console.log('resolved 1200', res)}, (err) => {console.error('rejected 1200', err)}).then((res) => {console.log('res2', res)}, (err) => {console.log('err2', err)}).catch((res) => {console.log('catch2', res)})// promise 变成rejected,执行第一个rejected 1200// 然后第二个 then 会执行resolved 函数,但是拿不到 res// 没有抛出错误,所以 catch 不执行// rejected 1200 gua// res2 undefineda(2000).catch((res) => {console.log('catch2000, 1', res)}).catch((res) => {console.log('catch2000, 2', res)})// 第一个 catch 接住了抛出的错误,所以第二个没有得到// catch2000 1 guaa(3000).catch((res) => {console.log('catch3000', res)}).then((res) => {console.log('then 3000', res)})// 第一个 catch 接住了 错误(默认返回了一个resolved promise),然后 then 可以继续接
function Person(a,b,c) {this.a = athis.b = bthis.c = cthis.friends = [1,2,3]}Person.prototype = {constructor: Person,sayName: function() {console.log(this.a)},}
function Man(a,b,c,d) {Person.call(this, a, b, c)this.d = d}Man.prototype = new Person()Man.constructor = ManMan.prototype.logD = function() {console.log(this.d)}
// 定义类class Point {// 构造函数constructor(x, y) {this.x = x;this.y = y;}get prop() { // Point.prop 的 getter 函数,调用时返回值// do somethingreturn 'hahaha'}set prop(value) { // Point.prop 的 setter 函数,在赋值的同时执行console.log('设置 prop 为' + value)}static method1() {// 一个静态方法,不会被实例获取的,但是会被子类继承调用console.log('静态函数 method1,可被类调用,不可被实例调用')}method2() {console.log('这里是 method 2,可被实例调用,可被子类继承')return '(' + this.x + ', ' + this.y + ')';}}// 继承类class ColorPoint extends Point {constructor(x, y, color) {super(x, y) // 调用父类的constructor(x, y)this.color = color}method3() {return this.color + ' ' + super.method2(); // 调用父类的toString()}}
export与export default 均可用于导出常量、函数、文件、模块等import a from '/path/b'的方式,将其导入,以便能够对其进行使用export、import可以有多个,export default仅有一个export方式导出,在导入时要加{ },export default则不需要
import defaultExport from "module-name" // export defaultimport "module-name" // export defaultimport * as name from "module-name" // export,引用时 name.aimport { a as alias } from "module-name"; //export// alias 别名
Set Map
https://zhuanlan.zhihu.com/p/23155051
从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
- 不同端口 不同协议(http https) 不同域名
监听媒体元素的事件 onplay onpause onended 等等
amd 是 requireJS 推广时的定义模块规范,提前执行
cmd 是 seaJS 推广时的定义模块规范,延迟执行
- yarn 并发安装,安全可靠,非常快 yarn.lock
- npm 允许安装 packages 时执行代码
- yarn 并非想要完全取代 npm ,它只是一个新的 CLI 工具,拉取的 packages 依然来自 npm。
- 都是通过 package.json 记录项目需要拉取的依赖文件。
- 内容
- 减少 http 请求次数
- 减少 DNS 查询
- 减少重定向次数
- ajax 可以缓存 Expires Cache Control Header 头
- 首屏以外的组件延迟加载
- 猜测用户的使用倾向,预加载
- 减少 html 的 dom 数量
- 跨域分离组件, 可以多服务器并行
- 杜绝 404
- 少用 iframe
- CSS:
- 样式表放在顶部
- 引入 css 时使用 link 不用 import
- 避免使用滤镜
- JS :
- script 放在最后
- 少操作 dom,避免重绘
- 去除重复的 script
- 多用事件委托
- 图片:
- 压缩图片
- 使用雪碧图 / base64
- 不用 html css 设置图片的大小,而尽量使用原图的大小
- cookie:
- 给 cookie 减肥
- 把静态资源放在与 cookie 无关的域名下
window.addEventListener("hashchange", funcRef, false)先设置 height:1px transform:scaleY(0.5)