前端面试问题 —— js

1. 防抖和节流?滚动用防抖还是节流(都可以吧)

2. call和apply的区别?怎么实现call?

就参数不一样,call是参数序列,apply是数组

call实现
Function.prototype.call2 = function(obj,...arg) {
    console.log('指向对象:' , obj , '函数:', this , '函数参数:', arg)
   
   //判断是否为空,否则指向全局
    if(obj == null){
        obj = window
    }
    
    // 采用方法就是在指向目标对象中加入一个函数,并执行,然后删除,这样函数内的this指向就是目标对像了
    obj.fn = this;
    var res = obj.fn(...arg);
    delete obj.fn;
    
    //添加返回值,就是返回函数执行结果
    return res
}

3. 闭包的使用场景和缺点

学习Javascript闭包(Closure)

闭包就是:函数内部会返回一个函数,使得在函数外部调用函数内部的变量,这个返回的函数就叫做闭包。

我的理解是,闭包就是能够读取其他函数内部变量的函数。

闭包的缺点:比普通函数占用更多的内存。可以通过不使用了就释放解决这个问题。
滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露

使用闭包的好处是不会污染全局环境

闭包可以用在许多地方。它的最大用处有两个,
1、一个是前面提到的可以读取函数内部的变量,
2、另一个就是让这些变量的值始终保持在内存中。

闭包的常用场景:
一是函数作为返回值:
防抖和节流函数、立即执行函数正确获得索引值(for+setTimeout)、函数柯里化

二是函数作为参数来传递。
不适用于返回闭包的函数是个特别大的函数,很多高级应用都要依靠闭包实现.

4. 实现数组去重

5. 箭头函数

优点:
相当于匿名函数,简化了函数的定义

使用注意事项:
1、箭头函数是匿名函数,不能作为构造函数,不能使用new2、箭头函数的this
会捕获其所在的上下文的this值,作为自己的this值。
this指向当前函数的上上个函数。
var obj = {
  a: 10,
  b: () =>{
    console.log(this.a, this); // undefined, Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  },
  c: function() {
     return ()=>{
            // 这里的this是c所在的上下文,所以有a值
           console.log(this.a); //10
     }
  }
}
obj.b(); 
obj.c()();

3、 不能用arguments
在使用箭头函数时,arguments 指向的对象并不是当前函数所属的argments,而是上级函数的arguments,所以需要将箭头函数转为function。会报错;Uncaught ReferenceError: arguments is not defined
// 获取参数可以使用扩展运算符
let C = (...c) => {
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]

4、箭头函数通过 call() 或apply() 方法调用一个函数时,对 this 指向 并没有影响。


5、箭头函数没有原型属性
var a = ()=> 1 ;
console.log(a.prototype);  // undefined

只有函数才有prototype,对象一般是通过_proto_ 获取prototype。

6、箭头函数不能当做Generator函数,不能使用yield关键字


6. js继承?

https://www.cnblogs.com/Grace-zyy/p/8206002.html

7. 原生js什么时候知道页面加载完成

window.οnlοad=function(){
  //somecode
}

jqury中的ready()与onload()的区别

8、webworkers

当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。
您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

http://www.ruanyifeng.com/blog/2018/07/web-worker.html

9、for 、forEach、for in 、 for of 、while区别

for i : 这种写法比较麻烦

forEach :没有办法终止循环,用break报错,return的作用在这里跟continue一样


for...in循环主要是为遍历对象而设计的,它还会遍历手动添加的、原型上的键(enumerable:true)
(可以使用Object.propertyIsEnumerable(属性名)是不是存在于对象上的键,而不是原型上的)
所以遍历键的方法:
 1for...in 
2、Object.keys(myObject)不会遍历原型上的键, 同样属性要满足enumerable:true)
3、Object.getOwnPropertyNames(myObject), 所有属性,无论是否可枚举

hasOwnProperty 和 in的区别:
person1.hasOwnProperty("name")只在属性存在于实例中时才会返回true
"name" in person1 除了实例还回去原型上找

for...in 如果用于数组要注意:
1、键名是字符串类型的'1','2'... 
2、而且除了所有数值索引,还会包括所有的枚举类型(甚至原型上的)



for...of 是用于iterator接口,用for...of循环遍历它的成员。
iterator :(set、map、数组、generator、字符串)

10、for of跟promise和async await 有啥区别?for of 能不能放异步操作?

(我觉得是两类东西)大概共同点就是能够处理异步函数

能,我说generator函数返回的是一个Iterator,通过next执行yield调用异步,
所以for of应该也可以。
实际上在阮一峰es6中就说了,通过for of执行generator
function* foo() {
  yield 1;  yield 2;   yield 3;   yield 4;  yield 5;
  return 6;
}

for (let v of foo()) {
  console.log(v);
}
// 1 2 3 4 5

11、Object.defineProperty() 除了get和set,还有什么?

这个是访问描述符,还有数据描述符(value、writable、configurable、enumerable)

12、图片base64编码:

利用canvas里面的toDataUrl,现在一般UI框架上传图片都是编码好了的,比如vantUI

13、promise的all和race

Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

(1)、p1/p2/p3都是fullfilled时,p的状态才变成fulfilled,p1/p2/p3的返回值组成一个数组,传递给p的回调函数
(2)、只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
那个率先改变的 Promise 实例的返回值,就传递给p的回调函。

14、异步怎么捕获异常

一般捕获异常都是

try{
    throw new Error('fail');
    ...    //异常的抛出
}catch(e){
    ...    //异常的捕获与处理
}finally{
    ...    //结束处理
}

但是try模块里面是通过异步操作抛出的异常,异常就不能正常捕获到,但可以在异步代码里面加

try...catch 
  setTimeout(()=>{
        try{
            throw new Error('fail');
        }catch (e){
            console.log(e);
        }
    },1000);

或者通过浏览器错误监听:

window.onerror = function(x){alert(x)}
setTimeout(() => {
    throw new Error('fail');
    },1000)

比如promise的异常捕获是:

1、通过 .then((v)=>{} , (error) => { //错误信息处理 }}) , reject方法的作用,等同于抛出错误。
2.then(null, rejection)的别名:Promise.prototype.catch() :
promise.then(function(data) { 
    //cb
    // success
  }).catch(function(err) {
    // error——这个可以捕获到then里面的错误
    
  });

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

async await 捕获错误

1、使用catch方法
2、在异步代码外面包一层try catch
3、window.onerror全局监听

15、map和Object区别

1、object的键值只能是string或者symbol,map可以是所有数据类型(基本数据类型和对象函数等等) 2、map中键值对的顺序是依照写入的顺序,object是无序的,一定要说有什么规律就是数字键在前,字符键在后
3、map中有size方法得到键值对数量,object不行,只能遍历计数
4、map有 Iterator 接口,可以使用for…of遍历成员,object没有

16、promise .then的链式写法(阮一峰)

17、var 和let的区别?const初始不赋值?

1、变量只在let命令所在的代码块内有效。这个作用可以替代IIFE立即执行函数

{
   // 这个a 和外面的a互不影响,只存在这个块作用域
  let a = 10;
  var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

2、let不能重复定义变量,var可以
3、let不能变量提升,所以声明要在定义之前

const a :报错,const一定要初始化

const 赋值之后改变赋值怎么办?

分情况:
如果赋值是基本数据类型,之后再赋值会报错
如果是引用类型,像数组,对象等就可以改变内部的成员,因为const只要引用地址没变,不管堆上面的数据变化

18、this指向,bind

1、改变this指向

bind、call、apply、new(其实也是调用了apply)

2、bind之后调用call,能不能改变指向

不能
function func(){
    console.log(this.a,this.b,arguments)
}
func.bind({a:1,b:2},1).call({a:3,b:4},9)

打印 1,2 Arguments(2) [1, 9, callee: ƒ, Symbol(Symbol.iterator): ƒ]
bind 之后就不能改变

3、最顶层的function和箭头函数中的this指向

最顶层的this指向window
箭头函数的this默认指向在定义它时所处的对象(宿主对象)

19、判断对象是数组的方法。

4种,typeof得到的是object,不可以

var arr = []
isArray:  Array.isArray(arr) // true
instanceof: arr instanceof Array  // true
constuctor:  arr.constructor == Array // true
toString: Object.prototype.toString.call(arr)  //"[object Array]"

20、深拷贝和浅拷贝

对象:
https://www.jb51.net/article/160063.htm

浅拷贝
	obj1 = Object.assign({}, obj0)
深拷贝
	1、通过递归
	2JSON.stringify序列化,再JSON.parse反序列化。这个方法有局限:
		以下属性 -->  拷贝之后
		属性中有时间对象 --> 字符串
		regExp/Error对象 --> 空对象
		undefined --> 丢失
		NaNInfinity-Infinity --> null
		JSON.stringify()只能序列化对象的可枚举的自有属性	

数组:

浅拷贝:
	arrCopy = [...array]   
	数组其他拷贝的方法:map、forwhile、filter、reduce、slice、concat等等,都是浅拷贝
深拷贝:
	nums= [[1], [2]];
	numsCopy = JSON.parse(
	 JSON.stringify(nums)
	)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值