一些面试题(3)

1. 去掉数组中非数字字符, 并给每个数字+1

1
2
3
4
5
6
7
8
9
10
11
// 删除数组从后往前删 避免数组塌陷
var arr = [1, 2, 3, 'a', 4, 'b']
for(var i = arr.length - 1; i >= 0; i--){
console.log(typeof arr[i])
if(typeof arr[i] === 'number'){
arr[i]++
} else{
arr.splice(i, 1)
}
}
console.log(arr)

2. 再两个排好序的数组中, 高效率找出相同的元素放入新数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 两个变量 谁小谁往后移动  未排序先用  arr.sort排序后再查找
var arr1 = [1, 3, 7, 9, 12, 37, 45]
var arr2 = [2, 4, 9, 13, 45, 88, 92]
var result = []
for(var i = 0, j = 0;i<arr1.length && j<arr2.length;){
if(arr1[i] === arr2[j]){
result.push(arr1[[i]])
i++
j++
} else if(arr1[i]<arr2[j]){
i++
} else {
j++
}
}
console.log(result) // [2, 3, 4, 5]

3. 找出一个排好序的数组中, 两个元素相加和为19的元素组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arr4 = [1, 2, 4, 6, 7, 11, 12, 15, 17, 20]
var res = []
for (var i = 0, j = arr4.length - 1; i < j;) {
if (arr4[i] + arr4[j] > 19) {
j-- // 让大的往前移
} else if(arr4[i] + arr4[j] < 19){
i++
} else { // arr4[i]+arr4[j] === 19
res.push([arr4[i], arr4[j]])
i++
j--
}
}
console.log(res) // [9, 45]

4. hash 数组去重 会改变数据类型

1
2
3
4
5
6
7
8
9
var arr5 = [1, 2, 3, 4, '2', 1]
var hash = {}
for(var i=0;i<arr5.length;i++){
hash[arr5[i]] = 1
}
var res5 = []
var i = 0;
for(res5[i++] in hash){} // 利用对象遍历将key分别添加进数组res5中
console.log(res5) // ["1", "2", "3", "4"]

5. x in window

1
2
3
4
5
6
7
8
9
10
11
// var y var x---> window.x  window.y
// y = 10 -> ++y
// if(){} 不是作用域 拦不住内部的var变量被声明提前
var y = 10
if(!(x in window)){
var x = 10
} else {
++y
}
console.log(x) // undefined
console.log(y) // 11

6. 闭包 作用域链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function fun(n, o){ // fun 全局函数 随处可用
console.log(o) // 输出第二个参数
return {
fun: function(m){
return fun(m, n) // 只把第一个参数给孩子
}
}
}
var a = fun(0) // undefiend
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
var b = fun(0) // undefiend
.fun(1) // 0
.fun(2) // 1
.fun(3) // 2
var c = fun(0).fun(1); // undefiend 0
c.fun(2); // 1
c.fun(3); // 1

7. 默认参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// es6 如果函数的形参定义默认值 则函数体会包裹在一个匿名函数自调中运行
/*
function foo(x, y = function(){x=2}){
if(y===undefined){
y = function(){x=2}
}
(() => {
var x = 3
y()
console.log(x) // 3
})()
}*/
var x = 1;
function foo(x, y = function(){x=2}){
var x = 3
y() // 修改的是形参形成的临时作用域 将x=undefiend 修改为x=2
console.log(x) // 3 自己的作用域x依旧为3
}
// foo() 调用创建 临时函数作用域 x=undefiend y= function(){x=2}
foo()
console.log(x) // 1

8. FOO.a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Foo(){ // 第一步 创建地址Foo存储对象
Foo.a = function (){
console.log(1)
}
this.a = function (){
console.log(2)
}
}
Foo.prototype.a = function(){ // 构造函数原型上定义a方法
console.log(3)
}
Foo.a = function(){ // 构造函数静态方法
console.log(4)
}
Foo.a() // 4 执行Foo的静态方法 Foo.a = function(){ console.log(4) }
let obj = new Foo() // obj.__proto__ = Foo.prototype
// 执行Foo中的内容 Foo.a = function(){ console.log(1) } 将构造函数静态方法a
// 修改为 Foo.a = function(){ console.log(1) }
// this.a = obj.a = function (){ console.log(2) }
obj.a() // 2 obj.a = function (){ console.log(2) } 自身有a方法 否则会找 Foo.prototype.a
Foo.a() // 1 执行Foo的静态方法 Foo.a = function(){ console.log(1) }

9. foo.x 闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var x = 0;
var foo = {
x: 1,
bar: function(){
console.log(this.x)
var that = this
return function(){
console.log(this.x)
console.log(that.x)
}
}
}
foo.bar() // 1 this.x == foo.x
foo.bar()() // 1 0 1
//1. 先执行 foo.bar() 打印 1 that = this = foo
//2. 返回 function(){ console.log(this.x) console.log(that.x) }
//3. 匿名函数自调 function(){ console.log(this.x) console.log(that.x) }()
// this--> window this.x = window.x 打印 0 that--->foo that.x==foo.x 打印 1

10. obj.fn1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
var a = 2
var obj = {
a: 4,
fn1:(function(){
this.a *= 2
var a = 3
return function(){
this.a *= 2
a *= 3
console.log(a)
}
})()
}
// 1. 匿名函数自调 this--> window
/*fn1: (function(){
this.a *= 2 // window.a = a*2 = 4
var a = 3
return function(){ // a = 3 闭包中
this.a *= 2
a *= 3
console.log(a)
}
})()
执行后
a = 4
var obj = {
a: 4,
fn1: function(){ // a = 3
this.a *= 2
a *= 3
console.log(a)
}
}
*/
var fn1 = obj.fn1 // 9 fn1 = function(){ this.a *= 2; a *= 3; console.log(a) }
console.log(a) // 4 全局 window.a = 4
fn1() // 9
/*function(){ // a = 3 局部
this.a *= 2 // window.a = a*2 = 8
a *= 3 // a = a*3 = 9
console.log(a) // 9
}()*/
obj.fn1() // 27
/*function(){ // a = 9 局部
this.a *= 2 // obj.a = 4*2 = 8
a *= 3 // a = a*3 = 27
console.log(a) // 27
}*/
console.log(a) // 8 window.a
console.log(obj.a) // 8

11. 引用类型

1
2
3
4
5
6
7
8
9
10
function setObj(p){
// 形参函数局部作用域
// 形参 var p 然后赋值 p为0x1234
p.name='小红' // 将地址0x1234 name 修改为 小红
p = {} // 局部变量 p 指向新地址 0x5555
p.name="西西" // 将地址0x5555 name 修改为 xixi
}
var p = {name: '小明'} // 地址为0x1234
setObj(p)
console.log(p) // {name: "小红"} 局部变量 p 0x5555被系统回收

12. 判断一个属性是否在对象内

1
2
3
4
5
6
7
8
9
10
11
// 属性名 in obj --->是不仅判断一个属性是否在对象内部, 还判断是否在当前对象的原型链上
// obj.hasOwnProperty('属性名') ---> 仅判断是否在对象内部, 不检查原型链上
function People(firstname){
this.firstname = firstname
}
People.prototype.lastname = 'tew'
var bob = new People('tom')
bob.hasOwnProperty('firstname') // true
bob.hasOwnProperty('lastname') // false
'firstname' in bob // true
'lastname' in bob // true

其他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// getElements vs querySelectorAll
// getElements 返回的是动态集合,不存储实际数据,每次访问集合,都重新扫描DOM树
// querySelectorAll 返回的是非动态集合 存储实际数据, 每次访问集合,
// 都不重新查找DOM树,即使DOM树发生变化也不重新查找

/*
* 定时器
* 周期性定时器setInterval, 不会自动停止, 只能通过外部的变量timer来控制停止: clearInterval(timer)
* timer在clear之后,不会自动变为null,而是依然保存着已经关闭的定时器序号,需要手动设为null
*/

// let 和 setTimeout 一起使用时 块级作用域 相当于包裹了一个自执行函数 形成闭包
for(let i=0;i<3;i++){
setTimeout(()=>{
conolse.log(i)
}, 0)
}
// 0 1 2
/* 转换为es5之后
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(function () {
conolse.log(i);
}, 0);
})(i);
} */

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 定义一个新的People类继承 Animal中所有的属性和方法
function Animal(name, age){
this.name = name
this.age = age
}
Animal.prototype.intr = function(){
console.log(`I'm ${this.name}, I'm ${this.age}`)
}
/*
1. 让 person可以调用 Animal 原型上的方法 intr, 需要让 People.prototype继承Animal.prototype
Object.setPrototypeOf(People.prototype, Animal.prototype)
或者
People.prototype = new Animal()
或者
People.prototype = Animal.prototype
2. 使用 Animal.call(this, name, age) 方法继承父类的属性
*/

function People(name, age, className){
Animal.call(this, name, age)
this.className = className
}
// People.prototype = new Animal()
// People.prototype = Animal.prototype
Object.setPrototypeOf(People.prototype, Animal.prototype)
People.prototype.run = function(){
console.log(`我是${this.className}${this.name}, 我正在跑步`)
}
var person = new People('Tom', 20, '高一(2)班')
person.run()
person.intr()

promise 多个resolve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 1. first()-> new Promise 立即执行 输出 3 再立即执行new promise 输出 7
// 2. 将setTimeout放在异步队列
// 3. resolve(1)--> p.then(arg => { console.log(arg)}) 输出 1
// 4. resolve(2)--> first().then(arg => { console.log(arg) }) 输出 2
// 5. 执行 setTimeout 函数体 输出5
// 6. Promise中,只要遇到resolve,就会将resolve状态凝固,后边再出现其他的resolve,不会覆盖之前的resolve。
// 所有 resolve(6) 不会覆盖之前的resolve 也不执行 resolve(6)
const first = () => (new Promise((resolve, reject) => {
console.log(3)
let p = new Promise((resolve, reject)=>{
console.log(7)
setTimeout(() => {
console.log(5)
resolve(6)
}, 0)
resolve(1)
})
resolve(2)
p.then(arg => {
console.log(arg)
})
}))
first().then(arg => {
console.log(arg)
})
console.log(4)
// 3 7 4 1 2 5

promise 多个then

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 1. 将 setTimeout 放入宏任务队列
// 2. 立即执行 p1 = new Promise 输出 2 将p1.then(第一个then) 放入微任务队列
// 3. 立即执行 p2 = new Promise 输出 8 将p2.then(第一个then) 放入微任务队列
// 4. 执行 p1.then(第一个then) 输出 3 立即执行 p3 = new Promise 输出 4 将p3.then(第一个then) 放入微任务队列
// 5. 执行 p2.then(第一个then) 输出 9
// 6. 执行 p3.then(第一个then) 输出 5 返回一个promise 并将p3 的第二个then 放入微任务队列
// 7. 执行 p3.then(第二个then) 输出 6 此时 p1的第一个then执行完毕 返回一个promise 并将p1 的第二个then 放入微任务队列
// 8. 并将p1.then(第二个then) 输出 7 此时 微任务队列执行完毕
// 9. 执行宏任务 setTimeout 输出 1
setTimeout(() => {
console.log(1)
}, 0)

let p1 = new Promise((resolve, reject) => {
console.log(2)
resolve()
}).then(() => {
console.log(3)
let p3 = new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
}).then(() => {
console.log(6)
})
}).then(() => {
console.log(7)
})

let p2 = new Promise((resolve, reject)=>{
console.log(8)
resolve()
}).then(() => {
console.log(9)
})
// 2 8 3 4 9 5 7 6 1
-------------本文结束感谢您的阅读-------------
0%