1:js运行机制
js离不开用户的操作, js原理运行机制:单线程---->同一时间做同一件事
2:arguments的对象是什么
在JavaScript中,arguments属于当前对象的一个内置属性,arguments非常类似于Array对象,但是又不是实例的Array。 有属性无方法,类数组对象 箭头函数无arguments 转换为数组:
1:array.prototype.slice.call(arguments)
2:...
3:在调用这个函数时,代码中’b‘为啥会变成全局变量
function fun() {
//let a = b = 0
//转换为下面
let a=(b=0)
//从右往左执行,在为b赋值0的时候,因为没有b,会在引擎里创建b。又因为b没有声明,所以b会变成全局变量
}
4:哪些操作会造成内存泄露
1:闭包 2:意外的全局变量 3:被遗忘的定时器 4:脱离dom的引用(获取某div,然后它被清除了,但内存中仍然保存着对它的引用)
5:高阶函数
高阶函数:将函数作为参数的函数,或者将函数作为返回值的函数
function highOrder(params, callback) {
return callback(params)
}
6:var let和const的区别
- 使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象;
- 使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升;
- 使用const声明的是常量,在后面出现的代码中不能再修改该常量的值。 更深入了解的话请看我以前写的文章: var let和const的区别和 ES6的const
7:promise的概念和相关用法
1、Promise的含义 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
企业开发中为了保证异步代码的执行顺序,那么就会出现回调层层嵌套,如果回调函数嵌套的层数太多就会导致代码的阅读性,可维护性大大降低,promise对象可以将异步操作以同步流程来表示,避免了回调函数层层嵌套(回调地狱)
2、 Promise对象的基本特点
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中),fulfilled(已成功)和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为rejected 。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
3 .Promise的基本用法 我们通过console.dir(Promise)在终端打印一下,如下图所示
可以看到Promise是一个构造函数,他本身有 all, reject, resolve 方法,在他的原型上有 then, catch方法.
下面来创建一个Promise实例:
/*
*代码利用setTimeout函数实现异步操作,2秒生成一个数字,通过异步操作结果确定执行resolve函数还是reject函数
*/
function getNumber(){
return new Promise(function(resolve, reject) {
setTimeout(function(){
var number = Math.ceil(Math.random()*10);
if(number <= 5){
resolve(number)
}
else{
reject('数字太大了');
}
}, 2000)
})
}
getNumber()
.then(function(data){
console.log('resolve');
console.log(data);
},function(reason){
console.log('reject');
console.log(reason);
}
)
- Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。
- resolve函数的作用,将Promise对象的状态从“未完成”变成“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
- reject函数的作用是,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- then方法可以接受两个回调函数作为参数,第一个对应resolve的回调,第二个对应reject的回调。
Promise对象除了then方法,还有一个catch方法.它和then的第二个参数一样,用来指定reject的回调.用法如下:
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中
栗子如下:
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(odata);
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
如果要在三个异步操作执行完成后再执行某操作,那么就需要用到all方法. 如下:
function runAsync1(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
var number = Math.ceil(Math.random()*10);
console.log('1执行完成');
resolve(number);
}, 2000)
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
var number = Math.ceil(Math.random()*10);
console.log('2执行完成');
resolve(number);
}, 2000)
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
var number = Math.ceil(Math.random()*10);
console.log('3执行完成');
resolve(number);
}, 2000)
});
return p;
}
Promise.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(result){
console.log(result);
})
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
8:change,input,blur区别(change和input是如何实现的)
-
keydown事件发生时,输入值并没有发生变化,所以keydown可用于阻止某些输入字符的显示。
-
input事件发生时,无法获取到keyCode值,并且紧随在keydown事件之后。
-
keyup事件最后发生,一次键盘敲入事件彻底完成。
-
change事件只会发生在输入完成后,也就是输入框失去焦点之前。
-
输入完成后观察, 当用户完成所有的输入时,这时候必定会发生blur事件,只有这时才会触发change,所以可用blur与change监听用户输入是否完成,输入框的验证多半发生在此时。
-
输入框发生的事件流程依次为focus、keydown、input、keyup、change与blur,见下图所示。
ps:blur与change事件在绝大部分的情况下表现都非常相似,输入结束后,离开输入框,会先后触发change与blur,唯有两点例外。
1、没有进行任何输入时,不会触发change
在这种情况下失焦后,输入框并不会触发change事件,但一定会触发blur事件。在判断表单的修改状态时,这种差异会非常有用,通过change事件能轻易地找到哪些字段发生了变更以及其值的变更轨迹。
2、输入后值并没有发生变更
这种情况是指,在没有失焦的情况下,在输入框内进行的删除与输入操作,但最终的值与原值一样,这种情况下失焦后,keydown、input、keyup、blur都会触发,但change依旧不会触发。
9:去重的方法有哪些
1、ES6的new Set()
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
let set = new Set(arr);
console.log(set); // Set { 1, 3, 2, 5 }
console.log([...set]); // [ 1, 3, 2, 5 ]
console.log(Array.from(set)); // [ 1, 3, 2, 5 ]
2、双重for循环
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
for (let i=0, len=arr.length; i<len; i++) {
for (let j=i+1; j<len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
// splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
len--;
j--;
}
}
}
console.log(arr);
3、Array.sort() 使用sort()将数组进行排序,比较相邻元素是否相等,从而排除重复项
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
arr.sort((a, b) => a - b);
let result = [arr[0]]
for (let i=1, len=arr.length; i<len; i++) {
if (arr[i] !== arr[i-1])
result.push(arr[i]);
}
console.log(result);
4、for…of + Object 利用对象的属性不能相同
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
let obj = {};
let result = [];
for (let i of arr) {
if (!obj[i]) {
result.push(i);
obj[i] = 1;
}
}
console.log(result);
5、for…of + includes()
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
let result = [];
for (let i of arr) {
if (!result.includes(i)) {
result.push(i);
}
}
console.log(result);
6、Array.filter() + indexOf
let arr = [1, 1, 1, 3, 3, 2, 5, 5, 5];
let result = arr.filter((item, index)=> {
return arr.indexOf(item) === index;
})
console.log(result);
10:Array.from和new Set(arr))有哪些坑
1:
- Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。但是它会受到length属性的影响。无length属性的对象就不行。
- 缺点:
1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
2、该类数组对象的属性名必须为数值型或字符串型的数字
ps: 该类数组对象的属性名可以加引号,也可以不加引号
2:
new Set()对数组进行去重,但是返回的不是一个正常的数组,而是一个类数组结构。
11:深浅拷贝区别及实现方式
浅拷贝:创建一个新对象,有着原始对象属性值的一份精确拷贝。 如果属性是基本类型,拷贝的是基本类型的值。 如果属性是引用类型,拷贝的就是内存地址,如果其中一个对象改变了这个地址,就会影响到另一个对象
深拷贝:将一个对象从内存中完整的拷贝一份出来,放到从内存中新开辟的区域,且修改新对象不影响原对象
详见--深拷贝和浅拷贝
12:数组常用的方法介绍和用法,map,every,some等
1、filter:把符合条件的数组项返回,形成一个数组
var arrayObj = [15,3,2,6,7,1,9,10];
var result = arrayObj.filter(function(item,index,array){
return item > 7;
});//[15,9,10]
2、forEach() 用于遍历数组无返回值,会改变原来数组中的值
let arr = [1, 3, 12, 2, 20, -1, 6, 17];
arr.forEach((item, index, array) => {
array[index] = item * 2;
});
console.log(arr);// [2, 6, 24, 4, 40, -2, 12, 34]
3、map() 用于遍历数组,返回处理之后的新数组
const arr = [1, 3, 12, 2, 20, -1, 6, 17];
const newArr = arr.map((item, index, array) => item * 2);
console.log(arr); //[1, 3, 12, 2, 20, -1, 6, 17]
console.log(newArr);// [2, 6, 24, 4, 40, -2, 12, 34]
4、every() 用于判断数组中的每一项元素是否都满足条件,返回一个布尔值
const arr = [1, 3, 12, 2, 20, -1, 6, 17];
const bool = arr.every((item, index, array) => item < 12);
console.log(bool); // false
5、some() 用于判断数组中是否存在满足条件的元素,返回一个布尔值
const arr = [1, 3, 12, 2, 20, -1, 6, 17];
const bool = arr.some((item, index, array) => item < 12);
console.log(bool); // true
13:实现数组的交集和并集
let a = new Set([1, 2, 3]);
let b = new Set([3, 4, 5]);
let c = new Set([...a, ...b])
console.log(c) //1,2,3,4,5并集
let d = new Set([...a].filter(x => b.has(x)));
console.log(d); //3交集
14:如果有两个变量,在没有第三个变量时候,如何相互赋值
方法一,使用es6解构赋值
var a = 111
var b = 222
[a,b] = [b,a] // [222,111]
a = [a,b][0]
b = [a,b][1]
console.log(a); // 222
console.log(b); // 111
方法二,上一种方式的简写
var a = 111
var b = 222
a = [b,b=a][0] // 数组内从左向右开始赋值,第一个b=222,到了第二个b时,b=a=111。然后再取下标为0的b赋值给a,a=b=222
console.log(a); // 222
console.log(b); // 111
第三种方法,通过数值计算
通过两个数值变量的总和来计算出每一个变量的值然后再进行赋值。 因为第三种方法,因为是通过数值计算来达到变量交换,所以只能局限为进行数值类型的变量交换,如果变量交换类型非数值类型则会对交换的结果产生影响或者NaN。
var a = 111
var b = 222
a += b // a = a + b // 111 = 111 + 222,此时a为333
b = a - b // 222 = 333 - 222, 此时b为111
a -= b // a = a -b // 333 = 333 - 111, 此时a为222
console.log(a); // 222
console.log(b); // 111
以下为错误:---------------
var a = 1
var b = '哈哈'
a += b
b = a - b
a -= b
console.log(a);// NaN
console.log(b);// NaN
15:ES5和ES6用过哪些方法
es5:
• ES5 JSON扩展
JSON.parse JSON.stringify
ES5 Object扩展
Object.create Object.keys
Date对象
Date.now
ES5 Function扩展
Function.bind
ES5 String扩展
String.trim
ES5 数组方法扩展
Array.isArray Array.forEach Array.map Array.filter Array.some Array.every Array.indexOf Array.lastIndexOf Array.reduce Array.reduceRight
es6:
1. let/const 特性
2. 箭头函数
- 没有this、super、arguments和new.target绑定
- 不能通过new关键字调用
- 没有原型
- 不可以改变this的绑定
- 不支持arguments对象
- 不支持重复的命名参数
3. 字符串
.includes()判断字符串中是否包含某些字符串的时候 startWith() :如果在字符串的起始部分检测到指定文本则返回true
endsWith() :如果在字符串的结束部分检测到指定文本则返回true
4.模板字符串
单反引号
5.展开运算符
...
6.类 class
7. Set/Map
8. Promise
9.Async Await
16:class有了解过吗
详见。。写了再放