目录javascript
块级元素css
行内元素html
行内块级元素前端
h5java
// html <div class="left"></div> <div class="right"></div>
第一种方法:浮动css3
.left { float: left; width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; }
第二种方法:绝对定位git
body { position: relative; } .left { position: absolute; left: 0; top: 0; width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; }
第三种方法:flexes6
.parent { display: flex; } .left { width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; flex-grow: 1; }
.radius(@r:50%) { -webkit-border-radius: @r; -moz-border-radius: @r; border-radius: @r; }
IE67的混杂模式,宽度是算上了border + paddingweb
width = border-left + padding-left + con_width + padding-right + border-right
标准盒模型是分开来计算的面试
content-box 是w3c标准盒模型,其中的margin border padding width都是分别计算的,其中的width属性是只针对content的宽度。而border-box是IE67的混杂模型的盒模型计算方式,其中的width属性是盒模型的border + padding + content
div { -webkit-box-shadow: inset 5px 0 3px deepskyblue; -moz-box-shadow: inset 5px 0 3px deepskyblue; box-shadow: inset 5px 0 3px deepskyblue; }
box-shadow: inset h v blur spreed color
内阴影 竖直 水平 模糊 半径 颜色
link -> visited -> hover -> active
缘由以下:link和visited是常态,hover和active是即时状态,即时状态想要覆盖常态就必需要放到后面,不然无效。
一样,在常态里,visited是访问后的状态,想要覆盖未访问状态就要写到其后面;
即时态里,active想要覆盖hover就要写到后面
display: flex
设置这个属性后就会成为flex怪异盒模型
flex-direction
设置flex主轴的方向,属性值有:row/row-reverse/colum/colum-reverse
flex-wrap
设置换行的方式,属性值有:nowrap/wrap/wrap-reverse
justify-content
align-items
align-content
多根轴的对齐方式,若是只有一根轴就不生效order
数值越小越靠前,默认为0flex-grow
放大比例,如何去分配默认空间,0不放大,1均分,若是按其余比例,能够单独给项目设置flex-shrink
缩小比例,0不缩小,1等比例缩小,默认值是1复合写法是flex
align-self
单独设置对齐方式相关知识点:
跨域是浏览器的行为
跨域须要服务端的配合,若是不能修改服务端,能够本身后台转发一下请求,毕竟后台请求是没有跨域限制的
跨域的方式有几种,面试官要是问跨域的方式的话,通常就是在问JSONP。和面试官讲请JSONP的原理也算一点加分项。
相关知识点:
总而言之,就是使用script标签把数据请求回来。
通常印象中,script标签就是外链一段js代码。如今写一个服务,当浏览器访问/js
时,就send('alert("js")')
,发送一段js代码。如今看是否会执行
能够看到js代码正常执行了。这个就等于直接往全局做用域里直接写了一行alert('js')
这个时候咱们再返回一个JSON串回去
能够看到,直接报错了。这个就比如,直接往全局做用域里直接赤裸裸的扔了一个对象,没有任务操做。
假如咱们在全局做用域里已经定义好了一个函数
function handle(data) { console.log(data); }
若是用script标签请求回来的数据,能直接用这个函数处理多好。因此后台给咱们处理的时候
res.send('handle({name: "chang"})')
这个返回的数据和上面同样,也至关于直接在全局做用域里写了个
handle({name: "chang"});
这个时候咱们早已经定义好了处理函数,那么这个函数就能够直接处理数据了
因此无论哪一个工具封装的JSONP都是这个操做,也就是为何要和后台定义回调函数的名称,由于后台不知道你在JS定义什么名称的函数来处理数据,通常这个回调函数名称是须要放在queryString
中的。后台须要截取,再拼接
如下就是简单的JSONP代码
function xxxx(content) { console.log(content); } let script = document.createElement('script'); script.src = 'http://127.0.0.1:8000?cb=xxxx'; document.body.appendChild(script);
因此综上,jsonp只能是get请求
fetch是以前浏览器的xhr
对象的替代方案,如今使用的话,有浏览器兼容问题,毕竟有些浏览器是不支持的,可使用whatwg-fetch
这个包来解决一下。
和原生的xhr同样,都不会直接使用原生,而是使用封装好的库。
和原生的xhr
相比,优势:
async/await
,写的就像同步代码同样爽try { let response = await fetch(url); let data = await response.json(); console.log(data); } catch(e) { console.log("error:", e); }
使用的坑:
fetch(url, {credentials: 'same-origin'})
同域下发送cookiefetch(url, {credentials: 'include'})
跨域下发送cookie一种先后台通讯的方案,后台能够主动给前台推送消息,而取代以前的短轮循和长轮循
说出下面数字的输出顺序:
console.time('setTimeout'); console.time('setImmediate'); setImmediate(() => { console.log(1); console.timeEnd('setImmediate'); }); setTimeout(() => { console.log(2); console.timeEnd('setTimeout'); }, 0); process.nextTick(() => console.log(3)); new Promise(function(resolve){ console.log(4); resolve(); console.log(5); }).then(function(){ console.log(6); }); (() => console.log(7))();
答案:
4 5 7 3 6 2 1
解析:同步代码先顺序执行,而后是本轮循环的异步任务和次轮循环的异步任务。
process.nextTick
和Promise
就属于本轮循环的,并且process.nextTick
最早执行
其余两个属性次轮循环的异步任务,在setTimeout
的延迟时间为4ms及如下时,setTimeout
会先执行
var k; for (var i = 0, j = 0; i < 7, j < 10; i++, j++) { k = i + j; } console.log(k); var l; for (var i = 0, j = 0; i < 10, j < 7; i++, j++) { l = i + j; } console.log(l);
alert的时候会自动调用toString()
方法
alert([1, 3]); // -> 1, 3 alert({name: 'chang'}); // -> [object Object]
for (var i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, 1000*i); }
结果是连续输出5个5。setTimeout执行时,i已是5了,所有输出5很正常,如今的问题是时间间隔是多少。正确的姿式是,间隔时间是不相同的。(实验得知)
var obj = {name: 'Joo', age: 30}; ~function (n) { console.log(n); n.name = '中国'; n = {}; n.age = 5000; console.log(n); }(obj); console.log(obj);// {name: 'Joo', age: 30} // 形参 形式上的一个表明值 // 解耦 function add(a, b) { console.log(arguments.callee.caller); } // 实参 实际传入的参数 function a() { add(1, 4); } a();
方法 | 参数 | 返回值 | 是否影响原数组 | 发布版本 |
---|---|---|---|---|
push | length | y | ||
pop | item | y | ||
shift | item | y | ||
unshift | length | y | ||
splice | ||||
slice | ||||
concat | ||||
sort | ||||
toString | ||||
join | ||||
reverse | ||||
indexOf/lastIndexOf | ||||
forEach | ||||
every | ||||
some | ||||
filter | ||||
map | ||||
reduce/reduceRight | ||||
find/findIndex | ||||
includes | ||||
fill | ||||
entries/keys | ||||
Array.from | ||||
Array.of |
第一种方法:使用递归
var arr = [1, 2, [3, 4, [5, 6], 7], 8, [9, 10, [11]], 12]; var spreadArr = []; function spread(arr) { for (var i = 0; i < arr.length; i++) { if (arr[i] instanceof Array) { spread(arr[i]); } else { spreadArr.push(arr[i]); } } } spread(arr); console.log(spreadArr);
function bubbleSort(arr) { let isCompleted = true; for (let i = 0; i < arr.length - 1; i++) { for (let j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; isCompleted = false; } } if (isCompleted) { console.log('提早完成'); return arr; } else { isCompleted = true; } } isCompleted = null; return arr; }
function insertSort(arr) { let newArr = [arr[0]]; for (let i = 1; i < arr.length; i++) { let cur = arr[i]; for (let j = 0; j < newArr.length;) { if (cur > newArr[j]) { j++; if (j === newArr.length) { newArr.push(cur); break; } } else { newArr.splice(j, 0, cur); break; } } } return newArr; }
function quickSort(arr) { if (arr.length <= 1) { return arr; } let midIndex = Math.ceil(arr.length / 2); let midVal = arr.splice(midIndex, 1)[0]; let left = [], right = []; for (let i = 0; i < arr.length; i++) { let cur = arr[i]; cur < midVal ? left.push(cur) : right.push(cur); } return quickSort(left).concat(midVal, quickSort(right)); }
function unique2(arr) { let obj = {}; for (let i = 0; i < arr.length; i++) { let cur = arr[i]; if (obj[cur] === cur) { arr.splice(i, 1); i--; } else { obj[cur] = cur; } } return arr; }
function A(name) { this.name = name; this.sex = 1; } A.prototype.say = function () { console.log('hello world'); }; function B(age) { this.age = age; } let a = new A(); B.prototype = a; let b = new B(18); console.log(b);//{ age: 18 } console.log(b.name, b.sex);//undefined 1 b.say();//hello world /* * 原型链继承:子类的原型指定父类的实例 * * extend:继承了父类的私有和公有属性,在此处name和sex是私有属性,say是公有属性 * - 私有属性是从父类的实例上获得的 * - 公的属性是沿着做用域链b.__proto__ --> a (没有) --> a.__proto__ --> A.prototype (保存在此处) * * 原型链继承的问题: * - 继承父类的私有属性时,没法向父类型中传参,因此在输出b.name的时候是undefined * - 在继承引用数据类型的值时,就会有问题,请看下例 * */ function SuperType() { this.color = ['red', 'blue', 'yellow']; } function SubType() { } SubType.prototype = new SuperType(); let instance1 = new SubType(); let instance2 = new SubType(); instance1.color.push('black'); console.log(instance2.color);//[ 'red', 'blue', 'yellow', 'black' ] //修改了instance1的属性的时候instance2的属性也会跟着变化,由于这个属性都是来自于它们的原型
function SuperType(age) { this.age = age; } SuperType.prototype.say = function () { console.log('hello world'); }; function SubType(age) { SuperType.call(this, age); } let sub = new SubType(18); console.log(sub);//SubType { age: 18 } console.log(sub.say);//undefined /* * call继承:让父类的构造函数在子类的构造函数里执行,并使用call改变里面的this * * extend:由于只是让父类的构造函数在子类里执行,因此只继承了私有属性。 * * 优势:和原型链继承相比,解决了没法传参的问题,这个参数能够写在call的第二个参数位置 * * 缺点: * - 由于只有私有属性继承,定义在父类原型上的方法对子类的实例都是不可见的 * */
function SuperType() { this.name = 'chang'; } SuperType.prototype.say = function () { console.log('hello'); }; function SubType() { SuperType.call(this); } SubType.prototype = new SuperType(); let sub = new SubType(); console.log(sub);//{ name: 'chang' } sub.say();//hello /* * 组合式继承:将原型继承和call继承组合使用 * * extend:使用call继承私有属性,使用原型链继承继承公有属性 * * 优势:解决了原型继承和call继承的问题 * * 缺点:父类的构造函数调用了两次 * * */
/* * 这种方法并无使用严格意义上的构造函数,借助原型能够基于已有的对象创新新的对象,同时还没必要建立自定义的类型 * */ function object(o) { function F() { } F.prototype = o; return new F(); } let obj1 = {name: 'chang', friend: ['a', 'b', 'c']}; let obj2 = object(obj1); console.log(obj2.__proto__);//{ name: 'chang', friend: [ 'a', 'b', 'c' ] } /* * 在es5中规范了这个继承的方法:Object.create(),这个方法接收两个参数,一个用做新对象原型的对象和(可选的)一个为新对象定义额外属性的对象 * */ let obj3 = Object.create(obj1); console.log(obj3.__proto__);//{ name: 'chang', friend: [ 'a', 'b', 'c' ] } //添加额外属性时,必须使用这种格式 let obj4 = Object.create(obj1, { like: { value: 'code' } }); console.log(obj4.like);//code
__proto__
function SuperType() { this.name = 'chang'; } SuperType.prototype.say = function () { console.log('ok'); }; function SubType() { } SubType.prototype.__proto__ = SuperType.prototype; let sub = new SubType(); console.log(sub.name);//undefined sub.say();//ok /* * 不知道名字的继承:改变子类的原型的__proto__,指向父类的原型 * 只继承公有 * */
setProtoOf
/* * Object.setPrototypeOf方法的做用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象自己。它是 ES6 正式推荐的设置原型对象的方法。 * * * */ let obj1 = {name: 'chang'}; let obj2 = {}; Object.setPrototypeOf(obj2, obj1); console.log(obj2.__proto__ === obj1);
var os = document.getElementsByTagName('*'); var cObj = {}; var max = 0; function sta(cName) { var cNameArr = cName.split(/ +/); for (var i = 0; i < cNameArr.length; i++) { var cur = cNameArr[i]; if (cObj[cur]) { cObj[cur]++; } else { cObj[cur] = 1; } } } for (var i = 0; i < os.length; i++) { if (os[i].className) { sta(os[i].className); } } for (var attr in cObj) { if (cObj.hasOwnProperty(attr)) { if (cObj[attr] > max) { max = cObj[attr]; } } } console.log(max);
let/const
includes/startsWith/endsWith
repeat
entries/keys/values
Array.from
将类数组转化成数组Array.of
将一级值转成数组includes
Object.assign
合并对象,浅拷贝Object.keys()/Object.values()/Object.entries()
Symbol
第6种基本数据类型的值 let s = Symbol() // 不须要new
Set
可用于数组去重var arr = [1, 1, 1, 1]; var s = new Set(arr); var newArr = [...s];
Map
和Object
相比,key值能够是任何值proxy
作目标对象的读写操做的拦截Promise
async/await
Class/extends
Module
经常使用命令(结合本身经常使用)
git add
git commit
git pull
git push
在多人协做开发的时候,若是不pull
是绝对push
不上去的git log
git log --pretty=oneline
git log --author=changzhn
git log -- filename
git log --grep=xxx
git show hash
查看当前的分支
git branch
git checkout -b develop
git checkout develop/release/master
git status
add
和commit
来产生版本号后,才能切换分支git stash
git stash list
git stash pop stash@{0}
好比切到release
分支上想合并develop
分支
git merge develop
找到版本号的时候想回退代码
git reset --HARD hash
push
上去,这个时候发现是推不上去的。git push origin master -f
-f
来暴力提交