一、JS中数组去重方法
1.ES5数组去重:使用indexOf(可返回某个指定的字符串值在字符串中首次出现的位置,如果首次出现,返回-1)
var arr = [1,2,3,1,3,4,5];
Array.prototype.myInfo = function(){
var newArr = [];
for(var i=0;i<arr.length;i++){
var a = newArr.indexOf(arr[i]);
if(a == -1){
newArr[newArr.length] = arr[i];
}
}
return newArr;
}
var result = arr.myInfo();
console.log(result);
2.ES6数组去重
(1)Set和Array.from
①ES6中新增了Set数据结构,类似于数组,但是它的成员都是唯一的 ,其构造函数可以接受一个数组作为参数
let array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
let set = new Set(array);
console.log(set);
// => Set(5) [1, 2, 3, 4, 5]
②ES6中Array新增了一个静态方法Array.from,可以把类似数组的对象转换为数组
let set = new Set();
set.add(1).add(2).add(3);
let array = Array.from(set);
console.log(array);
// => Array(3) [1, 2, 3]
③于是,现在我们可以用一行代码实现数组去重了
let array = Array.from(new Set([1, 1, 1, 2, 3, 2, 4]));
console.log(array);
// => Array(4) [1, 2, 3, 4]
(2)Set和rest
rest 方法操作符为“…”;… 将字符从数组中剥离出来
let arr = [1,2,1,2,3];
let result = new Set(arr);
console.log(result); // => Set(3) [1, 2, 3]
console.log(...result); // => 1, 2, 3
console.log([...result]); // => Array(3) [1, 2, 3]
console.log([...new Set(arr)]); // => Array(3) [1, 2, 3]
二、怎么获取数组中某个元素的索引
indexOf();
// 创建数组arr
let arr = [1, 2, 3, 4, 5];
// 得到1在arr数组中的下标0
arr.indexOf(1); // 0
三、JS中如何判断null、undefined、NaN
①判断undefined
var tmp = undefined;
if (typeof(tmp) =="undefined"){
alert("undefined");
}
说明:typeof 返回的是字符串,有六种可能(“number”、“string”、“boolean”、“object”、“function”、“undefined”)
②判断null
var tmp =null;
if (!tmp && typeof(tmp)!="undefined" && tmp!=0){
alert("null");
}
③判断NaN
var tmp = 0/0;
if(isNaN(tmp)){
alert("NaN");
}
说明:如果把 NaN 与任何值(包括其自身)相比得到的结果均是 false,所以要判断某个值是否是 NaN,不能使用 == 或 === 运算符。
提示:isNaN() 函数通常用于检测 parseFloat() 和 parseInt() 的结果,以判断它们表示的是否是合法的数字。当然也可以用 isNaN() 函数来检测算数错误,比如用 0 作除数的情况。
四、定时器、pormise/then、console.log()输出问题
五、vue父子组件周期顺序
Vue实例需要经过创建、初始化数据、编译模板、挂载DOM、渲染、更新、渲染、卸载等一系列过程,这个过程就是Vue的生命周期,Vue中提供的钩子函数有beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
父子组件嵌套时,父组件和子组件各拥有各自独立的钩子函数。
1.创建过程
创建过程主要涉及beforeCreate、created、beforeMount、mounted四个钩子函数。
父beforeCreate ->父Created -> 父BeforeMount ->子BeforeCreate ->子Created ->子BeforeMount ->子Mounted ->父Mounted
2.更新过程
更新过程主要涉及beforeUpdate、updated两个钩子函数,当父子组件有数据传递时才会有生命周期的比较。
父BeforeUpdate ->子BeforeUpdate ->子Updated ->父Updated
3.销毁过程
销毁过程主要涉及beforeDestroy、destroyed两个钩子函数,本例直接调用vm.$destroy()销毁整个实例以达到销毁父子组件的目的。
父BeforeDestroy ->子BeforeDestroy ->子Destroyed ->父Destroyed
六、说一下你对vue的认识
七、了解其他框架吗?vue和react有什么区别?
八、v-if和v-show
(1)区别:
- 手段:v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
- 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
- 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存后,然后再切换的时候进行局部卸载);v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
- 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗。
(2)总结:
- v-if判断是否加载,可以减轻服务器的压力,在需要时加载,但有更高的切换开销;v-show调整DOM元素的CSS的dispaly属性,可以使客户端操作更加流畅,但有更高的初始渲染开销。
- 如果需要非常频繁地切换,则使用v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
九、computed、methods、watch
1.computed计算属性顾名思义就是通过其他变量计算得来的另一个属性,计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要它们的响应式数据没有发生改变,多次访问这个数据计算属性会立即返回之前的计算结果,而不必再次执行函数。
2.watch侦听器是侦听一个特定的值,当该值变化时执行特定的函数。例如分页组件中,我们可以监听当前页码,当页码变化时执行对应的获取数据的函数。
3.computed是计算属性,methods是方法,都可以实现对 data 中的数据加工后再输出。不同的是 computed 计算属性是基于它们的依赖进行缓存的。计算属性 computed 只有在它的相关依赖发生改变时才会重新求值。这就意味着只要data 中的数据 message 没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数。而对于methods ,只要发生重新渲染,methods调用总会执行该函数。
拓展1:computed与methods
(1)首先最明显的不同就是调用的时候,methods要加上();
(2)我们可以使用 methods 来替代computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值;而使用methods ,在重新渲染的时候,函数总会重新调用执行。
(3)当有一个性能开销比较大的的计算属性 A ,它需要遍历一个极大的数组和做大量的计算。然后我们可能有其他的计算属性依赖于 A ,这时候,我们就需要缓存。也就是使用 computed 而不是 methods。但对于每次都需要进行重新计算的属性,我们最好使用 methods。
拓展2:什么情况下分别使用computed、watch、methods
(1)数据量大,需要缓存的时候用computed;每次确实需要重新加载,不需要缓存时用methods。
(2)尽量用computed计算属性来监视数据的变化,因为它本身就这个特性,用watch没有computed“自动”,手动设置使代码变复杂。
(3)虽然计算属性在大多数情况下是非常适合的,但是在有些情况下我们需要自定义一个watcher,在数据变化时来执行异步操作,这时watch是非常有用的。
十、组件传值
- 父子组件的关系可以总结为 props 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
- 兄弟组件传值:非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。
- 其他的:vuex、$parent / $children(通过parent / children可以获父 / 子组件实例,然后通过这个实例就可以访问父 / 子组件的属性和方法)与 ref(如果在普通DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例)。
①父组件给子组件传值:props
②子组件向父组件传值:通过事件
③兄弟组件传值:定义个公共的公共实例文件bus.js,作为中间仓库来传值
十一、vue全家桶(router和vuex)
十二、ES6常用特性
1.变量的改变,添加了块级作用域的概念(let、const)
2.模板字符串
在ES6之前,我们往往通过“\”和“+”来构建模板处理模板字符串:
$("body").html("This demonstrates the output of HTML \
content to the page, including student's\
" + name + ", " + seatNumber + ", " + sex + " and so on.");
而对ES6来说:①基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;②ES6反引号(``)直接搞定;
$("body").html(`This demonstrates the output of HTML content to the page,
including student's ${name}, ${seatNumber}, ${sex} and so on.`);
3.箭头函数(Arrow Functions):ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;
箭头函数最直观的三个特点。
- 不需要 function 关键字来创建函数
- 省略 return 关键字
- 继承当前上下文的 this 关键字
// ES5
var add = function (a, b) {
return a + b;
};
// 使用箭头函数
var add = (a, b) => a + b;
// ES5
[1,2,3].map((function(x){
return x + 1;
}).bind(this));
// 使用箭头函数
[1,2,3].map(x => x + 1);
4.Set数据结构与Array.from
var arr = [1,2,3,3,3,3,14]
var set = new Set(arr)
var arr = Array.from(set)
console.log(arr) // 1,2,3,14
5.函数的参数默认值
// ES6之前,当未传入参数时,text = 'default';
function printText(text) {
text = text || 'default';
console.log(text);
}
// ES6;
function printText(text = 'default') {
console.log(text);
}
printText('hello'); // hello
printText();// default
6.Spread / Rest 操作符:Spread / Rest 操作符指的是 …,具体是 Spread 还是 Rest 需要看上下文语境。
- 当被用于迭代器中时,它是一个 Spread 操作符:
function foo(x,y,z) {
console.log(x,y,z);
}
let arr = [1,2,3];
foo(...arr); // 1 2 3
- 当被用于函数传参时,是一个 Rest 操作符:
function foo(...args) {
console.log(args);
}
foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
7.对象和数组解构
// 对象
const student = {
name: 'Sam',
age: 22,
sex: '男'
}
// 数组
// const student = ['Sam', 22, '男'];
// ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex);
// ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);
8.for…of 和 for…in
- for…of 用于遍历一个迭代器,如数组:
let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
console.log(letter);
}
// 结果: a, b, c
- for…in 用来遍历对象中的属性:
let stus = ["Sam", "22", "男"];
for (let stu in stus) {
console.log(stus[stu]);
}
// 结果: Sam, 22, 男
9.类:ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类,与多数传统语言类似。
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
10.Promise:
- Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法
- Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来讲,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。不过在我们开始阶段可以先这么理解。
- 避免回调地狱:有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,然后给callback传进去吧。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。
11.字符串新增方法
let str = 'happy';
console.log(str.includes('ha')) // true
console.log(str.repeat(3)) // 'happyhappyhappy'
console.log(str.startsWith('ha')); // true,参数2为查找的位置
console.log(str.endsWith('p', 4)); // true,参数2为查找的字符串长度
十三、说一下你对JeeThink敏捷开发框架的认识
十四、Android的柱状图怎么实现的
MPAndroidChart组件。