这里写目录标题
HTML
CSS
九宫格
.myul{
list-style: none;
width: 400px;
height: 100px;
float: top;
}
.myli{
width: 80px;
height: 80px;
margin: 10px;
float: left;
background-color: red;
border-radius: 50%; /*轮廓圆角*/
}
<div class="mydiv">
<ul class="myul">
<li class="myli"></li>
<li class="myli"></li>
<li class="myli"></li>
</ul>
<ul class="myul">
<li class="myli"></li>
<li class="myli"></li>
<li class="myli"></li>
</ul>
<ul class="myul">
<li class="myli"></li>
<li class="myli"></li>
<li class="myli"></li>
</ul>
</div>
- 10.26:
float
建议用flex-flow: row wrap
代替
三栏布局
.container{
display: flex;
width: 1000px;
height: 500px;
}
.left{
flex-basis: 200px;
background-color: red;
}
.right{
flex-basis: 100px;
background-color: blue;
}
.middle{
flex: 1;
background-color: green;
}
<div class="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
- flex-basis 属性用于设置或检索弹性盒伸缩基准值。(即弹性盒元素的初始长度)
- flex 属性用于设置或检索弹性盒模型对象的子元素如何分配空间。(让所有弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容)
- 参考:flex属性-flex:1到底是什么
半圆
.mysemi{
width: 50px;
height: 100px;
border: 1px solid transparent; /*width style color*/
background-color: red;
border-radius: 100px 0 0 100px; /*左上 右上 右下 左下*/
}
<div class="mysemi"></div>
三角形
.tri{
width: 0;
height: 0;
border: 50px solid;
border-color: red transparent transparent transparent; /*上 右 下 左*/
}
<div class="tri"></div>
JS
基础
DOM
- 复选框操作
dom.checked = true; //false
E-mail正则表达式
let reg = /^ \w+ ([-+.] \w+)* @ \w+ ([-.] \w+)* \. \w+ ([-.] \w+)* $/;
对象
深拷贝
- 递归
const deepCopy = obj => {
let newobj = {};
for(let i in obj) {
if(typeof obj[i] != Object)
newobj[i] = obj[i];
else
newobj[i] = deepCopy(obj[i]);
}
return newobj;
};
//浅拷贝:Object.assign(newobj, obj);
//Object.create()是另一个方法
- 孤儿写法
let newobj = JSON.parse(JSON.stringify(obj));
new操作符的过程
- 以
classA
为例
- 生成空对象
let obj = {};
- 绑定原型和构造函数
obj.__proto__ = classA.prototype;
obj.constuctor = classA; //不用
- 绑定this
classA.apply(obj, arguments);
- 返回
组合继承
//警告:可以用const 慎用箭头函数
const Father = function(name) {
this.name = name; //父类属性1
};
Father.prototype.getName = function() {
return this.name; //父类方法1
};
const Son = function(name, age) {
Father.call(this, name);
this.age = age; //子类属性2
};
Son.prototype.getAge = function() {
return this.age; //子类方法2
}
//继承1:原型指向父类实例
Son.prototype = Object.create(Father.prototype);
//继承2:原型的构造函数指回
Son.prototype.constructor = Son;
//测试
let s1 = new Son("hello", 18);
console.log(s1.getName()); //输出hello
函数
函数参数引用传递
- 基本数值(Number、Boolean、String):值传递,只给值的副本
- 复杂类型(Ojbect、Array):引用传递,给你引用此地址的一个指针
- 如果你在指针基础修改,则原地址内容也会修改
- 如果你把此指针指向其他位置,则原地址内容更改不了
闭包
var add = (function () {
var counter = 0; //直接执行一次=初始化
return function () {return counter += 1;} //每次执行通过返回function改变值
//需要取出值用return 否则只做操作
})();
t = add();console.log(t); //1
t = add();console.log(t); //2
t = add();console.log(t); //3
//console.log(counter); //报错:闭包内定义不可使用
闭包实现m秒输出一个helloworld 输出k次
const test = () => {
let time = 5;
let timer = null;
return () => {
timer = setInterval(() => {
if(time > 0) {
console.log("hello world");
time--;
}
else
clearInterval(timer);
}, 100);
}
};
test()();
//传参则失去闭包的意义
//执行时则运行一次,初始化
//加监听器也是因为小闭包执行一次
函数柯里化
function add2(x) {
return function(y) {
return x + y;
}
}
//const add2 = x => y => x + y;
console.log(add2(1)(2)); //3
function add3(x) {
return function(y) {
return function(z) {
return x + y + z;
}
}
}
//const add3 = x => y => z => x + y + z;
console.log(add3(1)(2)(3)); //6
call、apply、bind的相互实现
- call和apply实现bind
Function.prototype.bindAsApply = function(target) {
let that = this; //保留当前this
let args = [].slice.call(arguments, 1); //arguments.slice(1)的合法写法
//args = [...arguments].slice(1); //另一种写法
return () => that.apply(target, args); //当前this使用apply,调用target和参数
};
Function.prototype.bindAsCall = function(target) {
let that = this; //保留当前this
let args = [].slice.call(arguments, 1); //arguments.slice(1)的合法写法
//args = [...arguments].slice(1); //另一种写法
return () => that.call(target, ...args); //当前this使用call,调用target和参数rest
};
//测试对象
let obj = {name : 'aaa'};
//测试函数
function test(...args) { //根据参数形式决定是否用rest
console.log('this:', this);
console.log('我的名字:', this.name);
console.log('我接收的参数:', args);
}
//测试语句
test.bindAsApply(obj, 1, 2, 3)();
test.bindAsCall(obj, 1, 2, 3)();
防抖和节流
- 防抖:利用计时器灵活赋值
function debounce(fn, delay){ //防抖
let timer = null;
return function(){
let that = this;
timer && clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(that, arguments);
}, delay)
}
}
- 节流:利用布尔值翻转
function throttle(fn, delay){ //节流
let tag = true;
return function(){
if(!tag)
return;
let that = this;
tag = false;
setTimeout(() => {
fn.apply(that, arguments);
tag = true;
}, delay)
}
}
ES56
for-in和for-of
- for in 总是得到key键值或者index索引(可用于对象 可枚举类型等)
for index in arr 遍历数组 index是索引 arr[index]是值 - for of 总是得到值(对象不可用)
for val of arr 遍历数组 val是值 - 要求可迭代对象,for i in 10 和for i of 10都不可
Array.sort()
回调函数的坑:
return a > b
结果为true和false 就是1和0 只有小于0才交换
return a - b
为正确写法
set进行数组去重
let a = [1, 2, 3, 4, 3, 2, 1];
a = [...(new Set(a))];
console.log(a);
mapAPI
//new
let mymap = new Map();
//基本方法
mymap.set('a', 1);
mymap.get('a'); //1
mymap.has('a'); //true
//遍历map
mymap.forEach((value, key) => {});
for(let item in mymap.values());
for(let item in mymap.keys());
for(let item in mymap); //数组
for(let item in mymap.entries()); //等价上面
//遍历计数的习惯写法
mymap.set(item, mymap.has(item) ? mymap.get(item) + 1 : 1);
交互
原生AJAX
- GET
const ajax = (url) => {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true); //信息存放在url中
xhr.send();
xhr.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200)
console.log(this.responseText);
}
}
- POST
const ajax = (url, objstring) => {
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //必备
xhr.send(objstring); //信息存放在字符串中发送
xhr.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200)
console.log(this.responseText);
}
}
· readyState
0:请求未初始化
1:服务器连接已建立
2:请求已收到
3:正在处理请求
4:请求已完成且响应已就绪
node.js建服务器
var http = require('http');
http.createServer(function (request, response) {
response.setHeader('Access-Control-Allow-Origin', '*'); //CORS跨域资源共享
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write('abc');
response.end('Hello World\n');
}).listen(8888);
算法
归并排序
const merge = (arrLeft, arrRight) => { //合并两个排序数组
let result = [];
while(arrLeft.length && arrRight.length)
result.push(arrLeft[0] < arrRight[0] ? arrLeft.shift() : arrRight.shift());
result = result.concat(arrLeft.length ? arrLeft : arrRight); //数组连接只能用concat并赋返回值,或者双rest(不好用)
return result;
};
const mergeSort = arr => {
const LEN = arr.length;
if(LEN < 2)
return arr;
else{
let mid = Math.floor(LEN / 2);
let arrLeft = arr.slice(0, mid);
let arrRight = arr.slice(mid);
return merge(mergeSort(arrLeft), mergeSort(arrRight)); //双路合并,嵌大排序
}
};
先前问题总结
面试时犯过的错误
- 深拷贝忘了说用JSON
- 默写完归并排序,考官问时间复杂度,我忘了
- 面试时说,对象的静态属性不常用
- 面试时说,自己不知道什么东西应该封装为组件(就是没深入学vue,还给自己找借口)
- 考官问,为什么没做移动端适配,写的css都是定死的长度宽度,连个百分比都没有,我无言以对
老异步问题:点击列表输出索引号
- HTML
<div class="a">文字</div>
<div class="a">文字</div>
<div class="a">文字</div>
<div class="a">文字</div>
<div class="a">文字</div>
- JS:var + onclick - 不可以,点哪个都是输出总长度
let a = document.getElementsByClassName('a');
for(var i = 0; i < a.length; i++) {
a[i].onclick = () => { console.log(i) };
}
- JS:var + 监听器 - 不可以,点哪个都是输出总长度
let a = document.getElementsByClassName('a');
for(var i = 0; i < a.length; i++) {
a[i].addEventListener('click', () => {console.log(i)});
}
- JS:let+ onclick - 可以
let a = document.getElementsByClassName('a');
for(let i = 0; i < a.length; i++) {
a[i].onclick = () => { console.log(i) };
}
- JS:let + 监听器 - 可以
let a = document.getElementsByClassName('a');
for(let i = 0; i < a.length; i++) {
a[i].addEventListener('click', () => {console.log(i)});
}
- JS:var + 闭包 - 可以
let a = document.getElementsByClassName('a');
for(var i = 0; i < a.length; i++) {
(function (item) {
a[i].addEventListener('click', () => {console.log(item)});
})(i);
}
- JS:let + 闭包 - 可以
let a = document.getElementsByClassName('a');
for(var i = 0; i < a.length; i++) {
(function (item) {
a[i].addEventListener('click', () => {console.log(item)});
})(i);
}
- 结论:
- 问题不在于是加
onclick
属性还是加addeventListener
监听器 - 问题只在于var,var定义变量的局限性
- 要么改成let,要么改用闭包,任何一个都可以工作