本章内容都是作者手动整理并且尽量缩减内容,
目的就是可以让开发者短时间内回顾知识碎片和面试问题。
常规
1.js如何查找元素以及他们的区别
document.querySelector('#id'); //静态获取节点(js新增的节点无法获取)
document.getElementById('#Id'); //性能更快更高效,动态获取节点
$('#id'); //使用了第一种原生js封装而成的
2.html新特性
①添加了新元素 footer header section nav progress audio video
②新增了 canvas 画布功能,该标签是图形容器,需通过js实现图画
③新增元素拖曳功能
首先设置元素可拖曳
然后可以调用相关事件:
拖动什么 - ondragstart 和 setData()
放到何处 - ondragover
进行放置 - ondrop
<img draggable="true" />
④HTML5地理定位功能(需要用户同意)
⑤新增 input
的类型:date week month time email tel
⑥新增web存储:sessionStorage、localStorage、webStorge
扩展:session local webStorge cookie的区别
cookie:存储空间只有4kb,在用户设定的期限后过期。
session:用户关闭当前标签页后失效,不同的标签页不共享session
local:除非浏览器中删除文件或者js删除否则一直存在
webStorge:大小扩展到 5mb,接口功能多,使用较复杂
⑦html5使用了离线存储功能,利用缓存离线访问,连网后再更新
⑧webStock:是一种浏览器和服务器可以相互通讯的协议,即服务器也可以主动发消息给浏览器。
⑨一些css3动画等
3.最常用的 Number 方法
数字转字符串
常用4中方法
let kolento = 1000+'';
kolento.toString();
kolento.toLocalString();
String(kolento);
区别扩展:
toString与toLocalString转化数字和时间的格式不同
String与上面2种相比,可以转化 null 与 undefine,
其他2种会报错,也就是他的使用范围更大
4.最常用 String 方法
①获取字符串长度
let kolento = 'hello';
kolento.length; 返回5
②返回指定位字符
let kolento = 'hello'
kolento.charAt(0) //返回第一个字符 h
③连接2个或者多个字符串
var a = 'aaa';
var b = 'bbb';
var c= 'ccc';
a.contact(b); //返回aaabbb
a.contact(b,c); //返回aaabbbccc
④检索字符串中的某个值
var kolento = 'hello';
kolento.indexOf('h'); //返回0,如果找不到返回 -1
kolento.match('h'); //返回值h,和相关对象信息
⑤替换字符串中的字符
let kolento = 'hello kolento kolento';
document.write(kolento.replace('kolento','Amiee'));
//返回 hello Amiee kolento
document.write(kolento.replace(/kolento/g,'Amiee'));
//返回 hello Amiee Amiee
⑥提取字符串的局部,并且返回一个新字符串
string.slice(start,end),返回内容不包括start,但是包括end(指定end情况下)
string.substr(start,length)
start:必须,开始下标,负数代表从尾部计算
length:返回长度
substring() 方法用于提取字符串中介于两个指定下标之间的字符
string.substring(start,stop) ,返回内容不包括start和stop,并且不接受负数参数
var str = 'hello happy world';
str.slice(1); //返回 ello happy world! ,开始1没有end
str.slice(4,9); //返回 lo hap 开始4,9结束
str.slice(-2)); 返回 d!,从末尾开始截取 开始-1,结尾-2
str.substr(0,7) //返回hello p
他们的区别在于第二个参数的意思不同
str.substring(2,5); //返回llo
返回内容不包括start和stop,并且不接受负数参数
⑦split方法将字符串分割成字符
string.split(separator,howmany)
separator : 分割符号
howmany:返回的数组长度
"2:3:4:5".split(":") //将返回["2", "3", "4", "5"]
"|a|b|c".split("|") //将返回["", "a", "b", "c"]
"hello".split("", 3) //可返回 ["h", "e", "l"]
注意:js的字符串都是不可变的,所有的转化修改都是返回一个新的字符串。而不是修改原始的字符串。
5.最常用 arr 方法
①返回数组长度其中的个数
let kolento = [1,2,3,4,5]
kolento.length //返回5
②连接2个或更多数组
var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
var arr2 = new Array(3)
arr2[0] = "James"
arr2[1] = "Adrew"
arr2[2] = "Martin"
arr.concat(arr2)
//返回 George,John,Thomas,James,Adrew,Martin
③数组组合成字符串
var arr = new Array(3);
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr.join();// George,John,Thomas 不添加分割符号,默认逗号
arr.join(".");// George.John.Thomas
④数组的添加与删除
pop(a) 删除返回数组的最后一项
push(a,b) 在数组最后添加一项或者多项,用逗号隔开
shift(a) 删除数组的第一项
unshift(a,b,c) 添加数组的第一项
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
arrayObject.splice(index,howmany,item1,.....,itemX)
index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany:必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, ..., itemX:可选。向数组添加的新项目。
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"
arr.splice(2,3,"William")
document.write(arr) //George,John,William,Martin
⑤颠倒数组的顺序
var a = 'hello';
s.reserve(); //返回 olleh
⑥slice方法截取数组中选定的部分
arrayObject.slice(start,end)截取内容不包括start,但是包括end,end是可选参数
let arr = [1,2,3,4,5]
arr.slice(1,3); //[2,3]
arr.slice(3); //[4,5]
⑦sort方法用于对数组进行排序
⑧toString() / toLocaleString()方法 ,数组转化成字符串
6.js各种循环之间的区别
①for循环:适合数组循环,性能一般
②for key in和for value of,适合json对象的循环
前者村换键,后者循环值,后者是es6新增
for(var key in obj){
// key 键,obj代表每个对象,obj[key]代表相对应的值
}
for(var value of obj){
// value代表键,obj代表每个对象
}
let aArray = ['a',123,{a:'1',b:'2'}]
for(let key in aArray){
console.log(key); //返回 0 1 2
}
for(var value of aArray){
console.log(value); a 123 {a:'1',b:'2'}
}
③forEach与map
let array = ['a','b','c']
array.forEach((currentValue, index, arr)=>{
console.log(currentValue); // a b c 必选参数
console.log(index); //0 1 2 可选参数
console.log(arr); // abc abc abc 可选参数
})
array.map(function(currentValue,index,arr){
console.log(currentValue); // a b c 必选参数
console.log(index); //0 1 2 可选参数
console.log(arr); // abc abc abc 可选参数
})
以上2者区别:
1.forEach是允许修改原始数组数据的,map的循环则是返回一个新数组。
2.forEach适合你不需要改变数据的时候使用,map可以在你改变数据的情况下使用。
3.map的性能高于forEach,快百分之70%左右
④jquery中的each
$(selector).each(function(index,element){
//都是必须的参数
//index - 选择器的 index 位置
//element - 当前的元素(也可使用 "this" 选择器)
})
⑤filter过滤
filter为“过滤”、“筛选”之意。指数组filter后,返回过滤后的新数组。用法跟map极为相似:
var arr = [
{"name":"apple", "count": 2},
{"name":"orange", "count": 5},
{"name":"pear", "count": 3},
{"name":"orange", "count": 16},
];
var newArr = arr.filter((value,index,arr)=>{
// value 当前元素的值 例如 {"name":"apple", "count": 2}
// index 0 1 2 等
// arr 整个数组
return value.name === "orange"; //返回2个name是orange的数组
});
7.window.location , window.location.href , window,location.replace的区别
有3个页面 a,b,c
如果当前页面是c页面,并且c页面是这样跳转过来的:a->b->c
1:b->c 是通过window.location.replace("..xx/c") 此时b页面的url会被c页面代替,并且点击后退按钮时会回退到a页面(最开始的页面)
2:b->c是通过window.location.href("..xx/c") 此时b页面的路径会被c页面代替,但是点击回按钮后页面回退的是b页面
两者的区别: 两者后退时所回退的页面不一样
8.js各种初始化之间的区别
此处列举了4种常见的初始化方式
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
<script>
$(function(){
alert("A");
});
$(document).ready(function(){
alert("B");
});
function load(){
alert("D");
};
window.onload=function(){
alert("E");
};
</script>
<body onload="load();">
</body>
</html>
运行下面代码。弹出A、B、D、E的顺序:A=B>D=E。
其中A和B都是在页面加载完,但是不包括图片多媒体数据加载完的情况。
C和D是在页面所有资源加载完后运行的。
9.css如何清除浮动
.clearfix:after{
content:".";/*加一段内容*/
display:block;/*让生成的元素以块级元素显示,占满剩余空间*/
height:0;/*避免生成的内容破坏原有布局高度*/
clear:both;/*清除浮动*/
visibility:hidden;/*让生成的内容不可见*/
}
.clearfix{zoom:1;/*为IE6,7的兼容性设置*/}
10.css中有哪些办法让一个 div 水平垂直居中
①flex布局
首先是他的兼容性,用在手机端问题不大
里面内容会自定居中
.parents {display:flex;justify-content:center;align-items: center;}
②定义table、table-cell
.parents {display:table;width:300px;height:300px;}
.child {display:table-cell;verital:middle;text-align:center;}
③定位窗体居中,常用在弹窗上
.child {position:fixed;width:300px;height:300px;top:50%;left:50%;
margin:-150px 0 0 -150px;}
11.谈谈对ES6的认识
具体解释://www.greatytc.com/p/287e0bb867ae
①新增变量声明,新增变量块作用域
const:声明常量
let:声明变量
②字符串模版,代码与变量拼接的时候特别好用。
③箭头函数
继承当前上下文的 this 指向
代码省略
④拓展的对象功能
ES5我们对于对象都是以键值对的形式书写,是有可能出现键值对重名的。例如:
function people(name, age) {
return {
name: name,
age: age
};
}
键值对重名,ES6可以简写如下:
function people(name, age) {
return {
name,
age
};
}
⑤解构赋值
⑥import(导入模块) 和 export(导出模块)
12.对json的了解
是一种轻量级的数据交换格式
格式简单,容易读写
把json字符串转化为json对象
var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);
json对象转化json字符串
var last = obj.toJSONstring();
var last = JSON.stringify(obj);
13.jq怎么添加删除元素
添加元素:
append():在末尾添加元素
prepend():在开头添加元素
after():在某个指定元素后添加元素
before():在某个指定元素前添加元素
删除元素:
a.remove(): 删除a
a.empty():删除a的子元素
14.数组去重
①js双层循环
首先定义一个新数组,数组中存放老数组的第一个元素。
然后循环老数组与新数组对比,如果值不相同就插入进新数组,最后形成一个没有重复的数组。
function unique(arr){
var res = [arr[0]];
for(var i=1; i<arr.length; i++){
var repeat = false;
for(var j=0; j<res.length; j++){
if(arr[i] === res[j]){
repeat = true;
break;
}
}
if(!repeat){
res.push(arr[i]);
}
}
return res;
}
②ES6数组去重
let array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
let set = new Set(array);
console.log(set);
// => Set {1, 2, 3, 4, 5}
15.浅拷贝与深拷贝的区别
简单的来说,如果b复制了a,但是在修改b的同时,a也改变了,则是浅拷贝。因为还是指向了原来的地方,如果只改变了自身,说明是深拷贝。
案例:
let a=[0,1,2,3,4],
b=a;
a[0]=1;
console.log(a,b);
这里明明只是修改了a数组,但是b也跟着发生了变化。
这里就要说一下基本数据类型和引用数据类型了。
基本数据类型:number,string,boolean,undefine,null
引用数据类型:obj,arr,function等
我们的基本数据类型是存储在栈内存中,let a = 1
当你b=a复制时,栈内存会新开辟一个内存,例如这样:
他们各自有自己的值,所以当你修改a=2的时候,并不会对b造成影响,因为他们有自己对应的值。当然,let a=1,b=a;虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。
引用数据类型,他们的属性名存在栈内存中,但是属性值存储在 堆内存中
当b=a复制的时候,其实只是复制了他的地址,而不是里面的值
而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了
如果我们在堆内存中开辟一个新的地址给b,b单独引用地址就算是深拷贝了。
这样修改a是不会影响b的
16.如何进行深拷贝
对象:
①首先判断类型,声明一个新对象保持继承链
②循环对象的key,输出key对应的值
③在循环中js动态添加新对象的属性和值完成深拷贝
var clone = function (obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor===Date) return new Date(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};
17.添加删除一个js对象的属性和值
添加:
var x = {a:1,b:2}
x.c=3
//返回 {a:1,b:2,c:3}
删除:
delete x.c //返回 {a:1,b:2}
18.vue的生命周期
具体可以看我的这篇文章
//www.greatytc.com/p/3afd8785b7f5
主要是这几个生命周期钩子
beforeCreated()
created()
beforeMounted()
mounted()
beforeUpdate()
updated()
activated()
deactivated()
beforeDestory()
destoryed()
1.在created钩子中可以对data数据进行操作,这个时候可以进行ajax请求将返回的数据赋给data
2.在mounted钩子对挂载的dom进行操作
3.在使用vue-router时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候created钩子就不会被重复调用了,如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。
4.beforeDestroy,页面组件内容销毁前使用,所有对象数据都会清空。
19.计算属性与监听的区别
当我们需要根据一个值来做一些操作的时候,可以使用计算属性,但是这个操作复杂,还牵扯到异步交互的时候,推荐使用监听属性更加合适。
20.v-if 与 v-show的区别
v-if:返回false时,元素节点都是删除的,返回true,重新渲染节点。
v-show:返回false时,元素节点为 display:none,true时 display:block
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if较好
21.父子组件如何通信
具体可以看我的这篇文章
//www.greatytc.com/p/00b7c4428574
父组件通信子组件
父组件在引用的子组件标签上添加动态的属性值
子组件中通过props获取父组件中的属性名,能够得到他的属性值
父组件
<div id="app">
<test :msg="childmsg" @parentevent="pevent"></test>
</div>
<script>
import test from './components/test'
export default {
name: 'App',
data(){
return{
msg:'',
childmsg:'这是传递给子组件的内容'
}
},
methods:{
pevent(){
console.log('这是子组件沟通父组件调用的父组件事件')
}
},
computed:{
},
components:{
test
}
}
</script>
子组件
<template>
<div class="test">
{{msg}}
<p @click="tryclick">点击试试</p>
</div>
</template>
<script>
export default{
props:['msg'],
data(){
return{
}
},
created(){
},
methods:{
tryclick(){
this.$emit('parentevent');
}
}
}
</script>
子组件通信父组件
由子组件向父组件沟通的事件为:emit
我们可以调用内建的 $emit
方法并传入事件的名字,来向父级组件触发一个事件
还是以之前的代码的例子作解释:
子组件p标签绑定点击事件,点击事件中触发
22.vue双向绑定的原理
当一个js对象传给vue实例的时候,vue会遍历他的所有属性值,并且通过Object.defineProperty把他转化成getter/setter,这个方法只有高级浏览器可用,所以ie9以下的浏览器不兼容。
其中的每个组件都有watch对象监听,当里面的值发生改变的时候,会调用setter,然后导致相关联的组件更新,并且更新视图。
23.vue的状态管理 vuex如何使用
具体可以看我的这篇文章
//www.greatytc.com/p/bc25eebcf15d
为什么要使用vuex
父组件:app
子组件:a,b
app与a,b之间的通讯没问题,但是a,b之间的通讯比较麻烦。
这里我们就可以使用vuex解决
我们可以在目录中新建一个js文件,store.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex'
Vue.use(Vuex);
Vue.config.productionTip = false
/* eslint-disable no-new */
const store = new Vuex.Store({
state:{
products:[
{name: '鼠标', price: 20},
{name: '键盘', price: 40},
{name: '耳机', price: 60},
{name: '显示屏', price: 80}
]
}
})
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
核心概念:
state,可以看成所有组件公共的data
可以通过 this.$store.state.products
来引用
getter,可以看成是所有组件的 computed 计算属性
获取方法
export default {
data () {
return {
products : this.$store.getters.saleProducts
}
}
}
Mutations,可以理解为 store 中的methods
store.js中的内容
mutations:{
minusPrice(state,payload){
let newPrice=state.products.forEach(product=>{
product.price-=payload
})
}
}
vue文件中通过commit调用vuex中的方法
this.$store.commit('minusPrice',2);
action,类似于上者,是用来存放方法的,不同的时,他可以加入异步方法。
触发方法
this.$store.dispatch('minusPriceAsync',5)
store中属性作用总结
目前我们已经在store中使用了四种属性了,回顾一下
1.state:用于存储状态,相当于公共data,可以让所有引入的组件获取。
2.getters:相当于计算属性,可以以data中的数据源为基础,返回一个新的data,而且这个data是随着 state中数据的改变而改变的。
3.mutations:相当于methods,在这个属性中可以再添加方法,可以传递 state作为第一个参数,和第二个payload作为自定义参数。其他组件可以通过 commit 来调用这里的方法,来改变视图
4.action:大致和mutations类似,但可以用于异步操作。
modules
当状态很多难以管理的时候,可以通过 modules 进行分类管理,划分为modules (a,b,c)等。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
25.如何进行响应式布局
大致思路如下
①首先需要添加meta标签
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
设置设备按照一比一的尺寸进行显示,并且禁止用户缩放页面
②使用媒介查询 @meida 在不同的分辨率下设置css
③单位尽量使用rem,宽度使用百分比