Javascrpt小测试
- JavaScript如何清空数组
- JavaScript数组去重
- 数组常用的方法
- MVVM的理解
- Vue生命周期有哪些函数
- Vue第一次加载页面会触发哪几个钩子函数
- 第一次获取el是在哪个生命周期中
- 第一次获取message是在哪一个生命周期中
- DOM渲染在哪个生命周期中就已经完成
- Vue中css只在当前组件起作用
- $ route和$router的区别
- v-if和v-show 区别
- vue.js的两个核心是什么?
- vue 几种常用的指令
- Vue 是单页面应用还是多页面应用
- 如何让一个盒子水平垂直居中(两种办法)
- 标签式跳转,函数式跳转 分别举个例子
- 标签式跳转传参
- 请举例三种定位以及他们的定位原点
- Let const 与var的区别
- 箭头函数this指向
- Undefined, not defind,null的区别
- 两种定时器
- Dom 是什么 Bom 是什么
- 数组转化为字符串,字符串转化为数组,字符串反转
JavaScript如何清空数组
splice函数
splice() 方法向/从数组中添加/删除元素,然后返回被删除的元素
var arr = [1,2,3];
arr.splice(0,arr.length);
console.log(arr);
给数组的length赋值为0
var arr = [1,2,3];
arr.length = 0 ;
console.log(arr);
直接赋予新数组 []
var arr = [1 ,2 ,3];
console.log(arr);
arr = [];
console.log(arr);
JavaScript数组去重
1: 思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中
function unique(arr) {
let newArr = [arr[0]];
for (let i = 1; i < arr.length; i++) {
let repeat = false;
for (let j = 0; j < newArr.length; j++) {
if (arr[i] === newArr[j]) {
repeat = true;
break;
}else{
}
}
if (!repeat) {
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
2: 思路:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组
function unique2(arr) {
var formArr = arr.sort()
var newArr=[formArr[0]]
for (let i = 1; i < formArr.length; i++) {
if (formArr[i]!==formArr[i-1]) {
newArr.push(formArr[i])
}
}
return newArr
}
console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 4,5, 6, 7]
3:利用对象属性存在的特性,如果没有该属性则存入新数组
function unique3(arr) {
var obj={}
var newArr=[]
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = 1
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
4: 利用数组的indexOf下标属性来查询
function unique4(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i])===-1) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
5:利用数组原型对象上的includes方法
function unique5(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (!newArr.includes(arr[i])) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique5([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
6: 利用数组原型对象上的 filter 和 includes方法
function unique6(arr) {
var newArr = []
newArr = arr.filter(function (item) {
return newArr.includes(item) ? '' : newArr.push(item)
})
return newArr
}
console.log(unique6([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
7: 利用数组原型对象上的 forEach 和 includes方法
function unique7(arr) {
let newArr = [];
arr.forEach(item => {
return newArr.includes(item) ? '' : newArr.push(item);
});
return newArr;
}
console.log(unique7([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 4, 5, 6, 7]
8: 利用数组原型对象上的splice 方法
function unique8(arr) {
var i,j,len = arr.length;
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
len--;
j--;
}
}
}
return arr;
}
console.log(unique8([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
9: 利用数组原型对象上的 lastIndexOf 方法
function unique9(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
res.lastIndexOf(arr[i]) !== -1 ? '' : res.push(arr[i]);
}
return res;
}
console.log(unique9([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
10: 利用ES6的set 方法
function unique10(arr) {
//Set数据结构,它类似于数组,其成员的值都是唯一的
return Array.from(new Set(arr)); // 利用Array.from将Set结构转换成数组
}
console.log(unique10([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
数组常用的方法
var arr = ["a","b","c","d"];
//push 在数组元素的末尾添加元素
//参数个数可以有很多个 末尾添加元素 ,返回当前数组的长度
var n = arr.push("e","f");
// 6
console.log(n);
// pop 在末尾删除一个元素,没有参数 返回被删除的元素
var del = arr.pop();
//f
console.log(del);
//e
arr.pop();//在末尾删除一个元素
// ["a", "b", "c","d"]
console.log(arr);
// unshift:在头部添加元素,返回当前数组的长度
arr.unshift(1,2);
//[1, 2, 'a', 'b', 'c', 'd']
console.log(arr);
//shift:在头部删除一个元素,返回被删除的元素
arr.shift();
// [2, 'a', 'b', 'c', 'd']
console.log(arr);
arr.shift();
//['a', 'b', 'c', 'd']
console.log(arr);
//1.splice(添加,删除,替换)
//splice(start,deleteCount,items(替换的内容))
var arr1 = ["a","b","c","d"];
arr1.splice(); //在原数组上进行的操作,返回被删除的元素
//1.1删除
//arr1.splice(1);//["a"] 一个参数表示从当前位置开始删除,删除到末尾
//arr1.splice(1,1); //"a", "c", "d"] start deleteCount 从1的位置开始删除,删除一个
//1.2 替换
arr1.splice(1,1,1); //["a", 1, "c", "d"] 从1的位置开始删除,删除一个,用1代替
arr1.splice(1,2,"c","f");
console.log(arr1);
//1.3 添加
var arr = [1,5,9];
arr.splice(1,0,4);//从第1(2)位开始操作 删除0个 添加的数是4
console.log(arr);//1,4,5,9 legnth4
//1 .sort() 对数组进行排序
var arr = [5,8,7,4,2,11,3,9,6];
arr.sort(); //默认从小到大,默认按字符串方式进行排序
//2.自定义排序 需要给sort传参,参数必须是函数
var arr2 = [5,8,7,4,2,11,7,3,9,6];
arr2.sort(function(a,b){ //相邻的两个数组元素
//return a-b; //第一个参数 - 第二参数 从小到大
return b-a; //第二个 - 第一个 从大到小
});
console.log(arr2);
//3.按date进行降序排序,如果date一样,按DIU进行降序排序
var arr3 = [
{"date":"2018-08-01", "DIU": 1209, "country": "US"},
{"date":"2018-08-02", "DIU": 680, "country": "GB"},
{"date":"2018-08-01", "DIU": 2311, "country": "CN"},
{"date":"2018-08-02", "DIU": 879, "country": "US"},
{"date":"2018-08-03", "DIU": 1525, "country": "CN"},
{"date":"2018-08-02", "DIU": 1525, "country": "CN"}
];
//Date.parse:将格式时间转换为具体的时间戳
console.log(Date.parse('2018-08-01'));
arr3.sort(function(a,b){
if(b.date === a.date){
return b.DIU - a.DIU;
}
return Date.parse(b.date)-Date.parse(a.date);
});
console.log(arr3);
//1.join 将数组按特定标志组合成字符串
var arr = [1,2,3];
console.log(arr.join('-'));
//2.reverse : 倒序
var arr = [1,2,3,4,5,6];
arr.reverse();
console.log(arr); //[6, 5, 4, 3, 2, 1]
//3.concat : 组合数组
var arr1 = [1,2,3];
var arr2 = ['a','b','c'];
var arr3 = ['hahah','heheh','heheh'];
var arr = arr1.concat(arr2,arr3); // 返回一个新的合并的数组
console.log(arr);
//4.indexOf : 元素是否存在数组中,在---返回下标,不在-1
var arr = [1,2,3,'html',5,6,7,8];
if(arr.indexOf('html')!=-1){
arr.splice(arr.indexOf('html'),1);
}
console.log(arr);
/*
数组的迭代方法
every :针对数组元素做些判断,如果结果都为true 则返回的结果为true
some : 针对数组元素做些判断,如果结果有一个为true 则返回的结果为true
filter : 针对数组元素做些判断,满足条件的元素,会组成一个新的数组,并且返回
map : 返回一个新的数组
forEach : 没有返回值,就是一个简单的循环
*/
//1.every:针对数组元素做些判断,如果结果都为true 则返回的结果为true &&
var arr = [true,false,true,true];
var isAll = arr.every(function (value,index) {
//数组的元素,数组的下标,当前数组本身 用value分别去比对 数组中的元素全部为true?
return value === true
});
console.log(isAll);
var arr1 = [6,7,10,8,9];
var s = arr1.every(function (value,index) {
return value > 5;
});
console.log(s);
//2.some : 针对数组元素做些判断,如果结果有一个为true 则返回的结果为true
var arr2 = [1,4,7,9];
var a = arr2.some(function (value,index) {
return value > 5;
});
console.log(a);
//3.filter:针对数组元素做些判断,满足条件的元素,会组成一个新的数组,并且返回
//其中正确的元素而组成一个新的数组
var arr3 = [3,7,4,9,1,6];
var arr4 = arr3.filter(function (value,index) {
return value > 5;
});
console.log(arr4);
//4.map:返回一个新的数组,将返回的值组合成一个新的数组
var arr5 = [1,2,3,4,5,6];
var arr6 = arr5.map(function (value,index) {
return value*value // [1, 4, 9, 16, 25, 36]
});
console.log(arr6);
//5.forEach 没有返回值,就是一个简单的循环
arr5.forEach(function (value,index) {
console.log(value);
})
MVVM的理解
MVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表。
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
- 该层向上与视图层进行双向数据绑定
- 向下与Model层通过接口请求进行数据交互
MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js
,Anfular JS
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处:
- 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑
- 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
- 可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
(1)View
View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。
(2)Model
Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
(3)ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。
需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的- 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
- 页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了View Model里。这样的封装使得View Model可以完整地去描述View层。由于实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。
MVVM框架已经把最脏最累的一块做好了, 我们开发者只需要处理和维护View Model, 更新数据视图就会自动得到相应更新,真正实现事件驱动编程
。
View层展现的不是Model
层的数据, 而是ViewModel
的数据, 由ViewModel
负责与Model
层交互, 这就完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
Vue生命周期有哪些函数
- 创建前/后:beforeCreate/created
- 挂载前/后:beforeMount/mounted
- 更新前/后:beforeUpdate/updated
- 销毁前/后:beforeDestroy/destroyed
Vue第一次加载页面会触发哪几个钩子函数
- 创建前/后:beforeCreate/created
- 挂载前/后:beforeMount/mounted
第一次获取el是在哪个生命周期中
挂在前,但是没有获取到data中的数据
第一次获取message是在哪一个生命周期中
创建后
DOM渲染在哪个生命周期中就已经完成
挂载后
Vue中css只在当前组件起作用
scoped
当 < style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素
$ route和$router的区别
$ route:路由信息
$router:跳转路由
v-if和v-show 区别
v-if:满足条件的渲染,不满足条件的不会渲染
v-show:结果都会渲染,但是满足条件的会通过display:block属性进行渲染,不满足条件的会通过display:none隐藏
vue.js的两个核心是什么?
数据驱动和组件化
vue 几种常用的指令
- v-if:根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 组件被销毁并重建。
- v-show:根据表达式之真假值,切换元素的 display CSS 属性。
- v-for:循环指令,基于一个数组或者对象渲染一个列表,vue 2.0以上必须需配合 key值 使用。
- v-bind:动态地绑定一个或多个特性,或一个组件 prop 到表达式。
- v-on:用于监听指定元素的DOM事件,比如点击事件。绑定事件监听器。
- v-model:实现表单输入和应用状态之间的双向绑定
- v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
- v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
Vue 是单页面应用还是多页面应用
单页面应用
如何让一个盒子水平垂直居中(两种办法)
- 定位 + Transform
思路:设置子盒子边偏移 top:50%,left:50%,再用CSS3属性transform: translate(-50%, -50%);
.box {
position: relative;
width: 800px;
height: 400px;
border: 1px solid black;
}
.son {
position: absolute;
width: 400px;
height: 200px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid red;
}
- Felx
思路:justify-content:center;设置flex盒子中的项目在主轴上居中对齐,align-items:center;设置flex盒子中的项目在侧轴和主轴上居中对齐,主轴和侧轴都居中了,盒子也就水平垂直居中了
.box {
display: flex;
justify-content: center; /* 设置flex盒子中的项目在主轴上居中对齐 */
align-items: center; /* 设置flex盒子中的项目在侧轴和主轴上居中对齐 */
width: 800px;
height: 400px;
border: 1px solid black;
}
.son {
width: 400px;
height: 200px;
border: 1px solid red;
}
标签式跳转,函数式跳转 分别举个例子
- 标签式跳转
<!-- 标签跳转页面 router-link to后面跟你在路由器配置文件里面path 浏览器编译完成后 是a标签-->
<router-link to="/page">点击page页面</router-link>
- 函数式跳转
<button @click="topage">函数式跳转</button>
topage() {
//函数式跳转
this.$router.push("/page");
}
标签式跳转传参
<router-link to="/user/yu">给user传参</router-link>
请举例三种定位以及他们的定位原点
- 固定定位是根据整个页面的
- 相对定位是相对自己本身初始的位置,不会脱离文档
流 - 绝对定位是根据父级设置了相对定位来偏移,父级没有设置相对定位就再上一级,都没有就对应整个页面,会脱离文档流
Let const 与var的区别
- let
1. 变量不能重复声明
2. 块儿级作用域 全局, 函数, eval
3. 不存在变量提升
4. 不影响作用域链 - const
1. 一定要赋初始值
2. 一般常量使用大写(潜规则)
3. 常量的值不能修改
4. 块儿级作用域
5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
6. 不存在变量提升 - var
- 定义的变量,没有块的概念
- 可以跨块访问, 不能跨函数访问
- 存在变量提升
箭头函数this指向
箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象
Undefined, not defind,null的区别
- undefined
不是一个报错,undefined是一种基础数据类型,也是挂载在window对象的一个属性,不是关键字。从js解析器的层面上解释,实际上是js解析到这个变量时,发现作用域里面没有这个变量.
window.undefined//undefined
情形一:当你引用了一个变量,变量被声明了,但没有初始化时,(we declare a variable without assigning any value to it),这个变量的值就是 undefined
let name;
console.log(name); //undefined
情形二: 引用了对象/数组中未声明的属性/方法
//Object
let obj = {a:3};
console.log(obj.b);//undefined
//Array
let arr = [1];
console.log(arr[1]);//undefined
- not defined
是一个报错,表示一个变量没有声明也没有定义(not declared at a given point of time )
console.log(b)//Uncaught ReferenceError: b is not defined
window.b = 5;
- null
null表示一个变量已声明定义了一个空值,表示一个空对象,是一个关键字:
两种定时器
- 延迟定时器:setTimeout
- 间歇定时器:setInterval
Dom 是什么 Bom 是什么
Dom:文档对象模型
Bom:浏览器对象模型
数组转化为字符串,字符串转化为数组,字符串反转
- 数组转化为字符串
let arr = ['adas', 'fff', 2, 3];
//adasfff23
console.log(arr.join(''));
- 字符串转化为数组
let str = 'carry';
//['c', 'a', 'r', 'r', 'y']
console.log(str.split(''));
- 字符串反转
let str = 'carry';
//['y', 'r', 'r', 'a', 'c']
console.log(str.split('').reverse().join(''));