Js经典面试题

在这里插入图片描述

1.什么是闭包?以及它的优缺点

闭包就是能够读取其他函数内部变量的函数,说白了闭包就是个函数,只不过是处于其他函数内部而已。由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数

优点:(1)访问函数内部的变量;(2)防止函数内部的变量执行完城后,被销毁,使其一直保存在内存中

缺点:由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除

2.Class和普通构造函数有何区别?

1、class在语法上更贴近面向对象的写法。
2、class实现继承更加易读易理解。
3、本质还是语法糖,使用prototype

3.IE和标准下有哪些兼容性的写法

1、var ev = ev || window.event
2、document.documentElement.clientWidth || document.body.clientWidth
3、var target = ev.srcElement||ev.target

4.什么是原型?什么是原型链?

原型:
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

5.面向对象的三大特征?

1、封装
把数据封装起来,减少耦合,不该外部访问的不要让外部访问。利于数据的接口权限管理,我们平时所用的方法和类都是一种封装,当我们在项目开发中,遇到一段功能的代码在好多地方重复使用的时候,我们可以把他单独封装成一个功能的方法,这样在我们需要使用的地方直接调用就可以了。


2.继承
我们想要一个对象能够访问另一个对象的属性,同时,这个对象还能够添加自己新的属性或者覆盖可访问的另一个对象的属性,我们实现这个目标的方式叫做“继承”。子类继承父类,继承可以把公共方法抽离出来,提高复用,减少冗余


3.多态
多态的具体表现为方法重载和方法重写:
(1)方法重载:重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数
(2)方法重写:重写(也叫覆盖)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样

6.实现继承有哪几种方式?
//这是父类方法
function Animal (name) {
  this.name = name || 'Animal';
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};

一、原型链继承
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat';
优点:
1.非常纯粹的继承关系,实例是子类的实例,也是父类的实例
2.父类新增原型方法/原型属性,子类都能访问到
3.简单,易于实现
缺点:
1.无法实现多继承
2.来自原型对象的所有属性被所有实例共享
3.创建子类实例时,无法向父类构造函数传参

二、构造继承
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; }
优点:
1.解决了子类实例共享父类引用属性的问题
2.创建子类实例时,可以向父类传递参数
3.可以实现多继承(call多个父类对象)
缺点:
1.实例并不是父类的实例,只是子类的实例
2.只能继承父类的实例属性和方法,不能继承原型属性/方法
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

三、实例继承
function Cat(name){ var instance = new Animal(); instance.name = name || 'Tom'; return instance; }
优点:
1.不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
1.实例是父类的实例,不是子类的实例
2.不支持多继承

四、拷贝继承
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } this.name = name || 'Tom'; }
优点:
1.支持多继承
缺点:
1.效率较低,内存占用高(因为要拷贝父类的属性)
2.无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)

五、组合继承
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal();
优点:
1.可以继承实例属性/方法,也可以继承原型属性/方法
2.既是子类的实例,也是父类的实例
3.不存在引用属性共享问题
4.可传参
5.函数可复用
缺点:
1.调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

六、Class 继承
class Cat extends Animal { constructor(name){     super(name);<br>    this.name= name || 'Animal'; } }
核心: 使用 extends 表明继承自哪个父类,并且在子类构造函数中必须调用 super,这段代码可以看成 Animal.call(this, name)。Class 的本质就是函数

7.手写一个冒泡排序
function bSort(arr) {
  var len = arr.length;
  for (var i = 0; i < len; i++) {
    for (var j = 0; j < len - i; j++) {
         // 相邻元素两两对比,元素交换,大的元素交换到后面
        if (arr[j] > arr[j + 1]) {
            var temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
  }
  return arr;
}
var myArr = [20,18,27,19,35];
console.log(bSort(myArr))
8.什么是Promise?Promise是用来干什么的?

1、Promise是一个构造函数,用于解决异步操作产生的回调地狱的问题
2、Promise 有三种状态,pending(等待状态)、resolve(成功状态)、reject(失败状态)
3、Promise 有一个then方法有两个参数,一个对应resolve的回调,另一个对应reject的回调,且可以接受他们传入的参数

4、常用的Promise的方法有刚才说的then、catch、all、race、finally
(1)catch用来捕获promise的错误函数,与then的第二个参数作用相同
(2)all用来执行多个promise函数(装在数组里),数组里所有任务的状态变为resolve之后,all的状态才可以变为resolve,只要有一个reject,all的状态就变为reject
(3)race也是用来执行多个promise函数(装在数组里),只要有一个改变状态(像赛跑一样),race的状态就会随之改变
(4)finally,不管成功与否,最后都会执行的函数

9.如何理解高阶函数

JavaScript中的一切都是对象,包括函数。我们可以将变量作为参数传递给函数,函数也是如此。我们调用接受和或返回另一个函数称为高阶函数的函数。

10.什么是防抖跟节流?

1、防抖:规定时间内再次触发事件,由于每次都会清除上一次的倒计时,所以它实际上只会真正执行最后一次处理; 对! 强调执行一次;所以很适合的场景有: input监听ajax候选词,防止点击多次提交

2、节流:规定时间内再次触发事件,由于是监听变量的方式,因此当变量重新被设置为true时,js又会执行;强调的是排队执行,可以执行多次;适合的场景有:滚动事件监听,多次响应点击等;

防抖实现:
document.querySelectorAll('button')[0].addEventListener('click', debounce(handle, 1000))
    function handle() {//要防抖的函数
        console.log("小凡好帅啊")
    }
    function debounce(fn, delay) {
        // 只产生一个闭包
        let timeId = null
        return function () {
        //用户每次点击都会进到这里来
            clearTimeout(timeId)
            timeId = setTimeout(fn, delay)
        }
    }
节流实现:
document.querySelectorAll('button')[1].addEventListener("click", throttle(f2, 1000))
    function f2() {//要节流的函数
        console.log("节流")
    }
    function throttle(fn, delay) {
        let flag = true
        return function () {
            if (!flag) {
                return
            }
            setTimeout(() => {
                fn.apply(this,arguments)
                flag = true
            }, delay)
            flag = false//过河拆桥
        }
    }
11.js清空数组的方法有哪几种?
var arr = [1,2,3,4,5];
//第一种:arr = [];
//第二种:arr.length = 0;
//第三种:arr.splice(0,arr.length);
12.document load 和$().ready的区别?

document.onload 是在结构和样式,外部js以及图片加载完才执行js
document.ready是dom树创建完成就执行的方法,原生种没有这个方法,jquery中有 $().ready(function

13.什么是图片懒加载,如何实现?

图片懒加载是为了降低一次性的 HTTP 请求数量,当图片很多时,或者同时在线人数较多时,图片懒加载可以起到很好的性能优化的作用。

实现:
1)设置自定义属性 data-src 来存储图片资源;
2)页面初始化或者在滚动时判断图片是否出现在可视区域;
3)在可视区域的话,将自定义属性 data-src 的值赋值给 src 属性。

class LazyLoad {
      constructor(tag) {
        this.boundTop = 0;
        this.clientHeight = 0;
        this.timer = null;
        this.aImg = Array.from(document.querySelectorAll(tag));
        this.init();
      }
      isShow(el) {
        this.boundTop = el.getBoundingClientRect().top;
        this.clientHeight = document.documentElement.clientHeight;
        return this.boundTop <= this.clientHeight - 100;
      }
      canLoad() {
        for(let i=0;i<this.aImg.length;i++) {
          let img = this.aImg[i]
          if(this.isShow(img)) {
            img.src = img.dataset.src
            //使用 for 循环是为了在改动数组后来操作 i,使得正确遍历每个元素
            this.aImg.splice(i, 1)
            i--          
          }
        }
      }
      addEvent() {
        window.addEventListener('scroll', () => {
          if(!this.aImg.length && this.timer) return;
          this.timer = setTimeout(() => {
            this.canLoad();
            this.timer = null; 
          }, 200);
        });
      }
      init() {
        this.canLoad();
        this.addEvent();
      }
    }

    let lazy = new LazyLoad('img');
14.为什么会有同源策略?

同源策略限制从一个源加载的文档或脚本如何与另一个源的资源进行交互。这是用于隔离潜在恶意文件的关键安全机制。
同源策略:协议相同、域名相同、端口相同,三者都必须相同

15.实现斐波那契数列以及优化?

什么是斐波那契数列:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, …
在种子数字 0 和 1 之后,后续的每一个数字都是前面两个数字之和。

N位数是几
实现1function fibonacci(n) {
    if(n==0 || n == 1)
        return n;
    return fibonacci(n-1) + fibonacci(n-2);
}
实现2let fibonacci = function() {
    let arr= [0, 1];
    return function(n) {
        let result = arr[n];
        if(typeof result != 'number') {
            result = fibonacci(n - 1) + fibonacci(n - 2);
            arr[n] = result; // 将每次 fibonacci(n) 的值都缓存下来
        }
        return result;
    }
}(); // 执行函数
实现3function fibonacci(n) {
    let current = 0;
    let next = 1;
    let temp;
    for(let i = 0; i < n; i++) {
        temp = current;
        current = next;
        next += temp;
    }
    console.log(`fibonacci(${n}, ${next}, ${current + next})`);
    return current;
}
16.JS查找字符串中出现次数最多的字符以及次数?
var str = "zhaochucichuzuiduodezifu";
var o = {};
for (var i = 0, length = str.length; i < length; i++) {
	// var char = str[i];
	var char = str.charAt(i);
	if (o[char]) { //char就是对象o的一个属性,o[char]是属性值,o[char]控制出现的次数
		o[char]++; //次数加1
	} else {
		o[char] = 1; //若第一次出现,次数记为1
	}
}
console.log(o); //输出的是完整的对象,记录着每一个字符及其出现的次数
//遍历对象,找到出现次数最多的字符和次数
var max = 0;
var maxChar = null;
for (var key in o) {
	if (max < o[key]) {
		max = o[key]; //max始终储存次数最大的那个
		maxChar = key; //那么对应的字符就是当前的key
	}
}
console.log("最多的字符是" + maxChar);
console.log("出现的次数是" + max);
17.call、apply、bind的用法及区别?

1、call:call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

2、apply:apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。

3、bind:和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数

18、ajax的使用及实现步骤?

(1) 创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2) 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.

function ajax(a) {
    return new Promise(function(resolve, reject) {
        a = a || {};
        a.type = a.type || "get";
        a.data = a.data || "";
        var xhr = null;
     
     // 处理兼容问题
        xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        if (a.type === "get") {
            a.url += "?" + Param(a.data) + "&t=" + new Date().getTime();
       //调用open()方法并采用异步方式
            xhr.open("get", a.url, true);
       //使用send()方法将请求发送出去
            xhr.send();
        } else if (a.type === "post") {
            xhr.open("post", a.url, true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhr.send(Param(a.data))
        }
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText));
                } else {
                    reject("Err:" + xhr.status)
                }
            }
        }

    })
}
19.ajax中get和post的区别?

1、GET可以通过在请求URL上添加请求参数,而POST请求则是作为HTTP消息的实体内容发送给WEB服务器。
2、GET方式请求数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取到这些数据,例如账号密码等。在某种情况下,GET方式会带来严重的安全问题。而POST方式相对来说就可以避免这些问题。
3、 Post请求必须设置请求头Content-Type值为application/x-form-www-urlencoded,如果没有设置,参数无法正确的传递到服务器(本质上说,如果没有参数,也不一定需要设置,不会影响请求的发送); get不用。
4、GET大小限制约4K,POST则没有限制(在http中”GET方式提交的数据最多只能是1024字节”,Post传输的数据量大,可以达到2M。 )

20.什么是事件委托?事件委托有哪些作用?

简单的来说,事件委托就是利用js事件冒泡的特性,将内层元素的事件委托给外层处理。
作用:可以减少dom的操作,减少不必要的重绘和回流,从而提升网页性能。

<body>
    <ul>
        <li id="one">我是1</li>
        <li id="two">我是2</li>
        <li id="three">我是3</li>
        <li id="four">我是4</li>
    </ul>
    <button id="btn">添加</button>
</body>
<script>
let oUl=document.getElementsByTagName("ul")[0];
let oLi=document.getElementsByTagName("li");

/*******原始写法*******/
for(let i=0;i<oLi.length;i++){            //遍历元素给每个元素添加点击事件
    oLi[i].onclick=function(){
        console.log(oLi[i].innerText);
    }
}
let btn=document.getElementById("btn");
btn.onclick=function(){                    //给按钮添加点击事件
    let aLi=document.createElement("li");     //创建新的li
    aLi.innerHTML=`我是${oLi.length+1}号`;
    aLi.onclick=function(){               //为新节点单独添加事件
        console.log(aLi.innerText);
    };
    oUl.appendChild(aLi);  
};

/*******使用代理写法*******/
oUl.onclick=function(ev){           //直接为ul添加点击事件
   ev=ev||window.event;            //ev对象的兼容处理
   let target=ev.target||ev.srcElement;   //通过ev对象的target找到触发事件的元素           
   if(target.nodeName.toLowerCase()=="li"){  //需求中的操作
      console.log(target.innerText);
   }
};
let btn=document.getElementById("btn");
btn.onclick=function(ev){               //为按钮添加点击事件
  let aLi=document.createElement("li");    //新建li元素
  aLi.innerHTML=`我是${oLi.length+1}号`;
  oUl.appendChild(aLi);    //直接将新元素放进ul
};
</script>
21.jsonp的原理?

原理:由于同源策略的限制,浏览器只允许XmlHttpRequest请求同源(域名、协议、端口相同)的资源,而对与请求script脚本资源却没有限制。通过包裹script标签来实现跨域请求,然后在服务端获取JSON数据并执行回调函数,这种跨域请求的方法被称为JSONP。

<script type="text/javascript">
   //添加<script>标签的方法
   function addScriptTag(src){
       var script = document.createElement('script');
       script.setAttribute("type","text/javascript");
       script.src = src;
       document.body.appendChild(script);
   }
   
   window.onload = function(){
       //搜索apple,将自定义的回调函数名result传入callback参数中
       addScriptTag("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=apple&callback=result");
       
   }
   //自定义的回调函数result
   function result(data) {
       //我们就简单的获取apple搜索结果的第一条记录中url数据
       alert(data.responseData.results[0].unescapedUrl);
   }
</script>
22.基本数据类型和引用数据类型有什么区别?

(1)两者作为函数的参数进行传递时:
基本数据类型传入的是数据的副本,原数据的更改不会影响传入后的数据。
引用数据类型传入的是数据的引用地址,原数据的更改会影响传入后的数据。
(2)两者在内存中的存储位置:
基本数据类型存储在栈中。
引用数据类型在栈中存储了指针,该指针指向的数据实体存储在堆中。

23.map和forEach的区别?

foreEach()方法:
针对每一个元素执行提供的函数。
map()方法:
创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来。


区别:
1、forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
2、map里可以用return ,而foreach里用return不起作用,foreach不能用break,会直接报错

24、Cookie、LocalStorage 与 SessionStorage的区别在哪里?
特性CookielocalStoragesessionStorage
数据的生命期一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效除非被清除,否则永久保存仅在当前会话下有效,关闭页面或浏览器后被清除
存放数据大小4K左右一般为5MB一般为5MB
与服务器端通信每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题仅在客户端(即浏览器)中保存,不参与和服务器的通信《–和左边localstorage一样
易用性需要程序员自己封装,源生的Cookie接口不友好源生接口可以接受,亦可再次封装来对Object和Array有更好的支持《–和左边localstorage一样
25.你对eval()的理解?

1.eval的功能是把对应的字符串解析成JS代码并运行
2.应该避免使用eval,不安全,而且非常消耗性能(2次,一次是解析成js语句,一次是执行)
3.由JSON字符串转换为JSON对象的时候可以用eval()

26.栈与堆的区别?

1、栈与堆的储存位置不同;
2、原始数据是储存在栈中简单数据段,体积小,大小固定,属于频繁使用的数据.
3、引用数据类型是储存在堆中的对象,占据的空间大,如果储存在栈中会影响运行性能,引用数据类型在栈中指明了自己的所在地。当代码解析时,会先从栈中获取地址,然后再从堆中获取实体;

27.new操作符在创建实例的时候经历了哪几个阶段?

new创建了一个对象,共经历了4个阶段:
1、 创建一个空对象
2、 设置原型链
3、让实例化对象中的this指向对象,并执行函数体
4、 判断实例化对象的返回值类型

28.js延迟加载的方法有哪些?

defer和async、动态创建DOM方式(用的最多),按需异步载入JS
(1)defer属性:(页面load后执行)
script标签定义了defer属性
用途:表明脚本在执行时不会影响页面的构造。也就是所,脚本会被延迟到整个页面解析完毕之后再执行。
(2)async属性:(页面load前执行)
script标签定义了async属性。与defer属性类似,都用于改变处理脚本的行为。同样,只适用于外部脚本文件。
目的:不让页面等待脚本下载和执行,从而异步加载页面其他内容。异步脚本一定会在页面load事件前执行。不能保证脚本会按顺序执行

29.js中常见的内存泄漏?

1、内存泄漏会导致一系列问题,比如:运行缓慢、崩溃、高延迟
2、内存泄漏是指你用不到(访问不到)的变量,依然占据着内存空间,不能被再次利用起来
3、意外的全局变量,这些都是不会被回收的变量(除非设置null或者被重新赋值),特别是那些用来临时存储大量信息的变量
4、周期函数一直在运行,处理函数并不会被回收,jq在移除节点前都会,将事件监听移除
5、js代码中有对DOM节点的引用,dom节点被移除的时候,引用还维持

30.一次性插入1000个div,如何优化插入的性能?

使用Fragment(document.createDocumentFragment( ))
Documentfragments是DOM节点,它们不是DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树中。因为文档片段存在于内存中,并不在DOM树中,所以讲子元素插入到文档片段时不会引起页面回流。因为使用文档片段会带来更好的性能

var divFragment = document.createDocumentFragment(); 
let div = document.createElement(“div”); 
   forvar i = 0; i <1000; i ++{ 
      divFragment.append(div.cloneNode())
    } 
document.body.appendChild(divFragment);
31.什么是伪数组,如何将伪数组转换为真数组?

伪数组:无法直接调用数组方法或期望length属性有什么特殊的行为,不具有push、pop等方法,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数等
伪数组的三大特性:
1、具有length属性
2、按索引方式存储数据
3、不具有数组的push,pop等方法
4、将伪数组转化为标准数组需要用到数组原型中的方法 slice
例如: Array.prototype.slice.call( 伪数组名称 );

32.JS手写sleep实现的三种方式?
一、第一种方式:使用Promise + setTimeout实现
function sleep(time) {
    return new Promise(resolve => {
        console.log(resolve)
        setTimeout(resolve, time)
    })
}
sleep(10000).then(res => {
    console.log(`sleep exe ending!`)
})
二、第二种方式:使用callback回调
function sleep(time, callback) {
    return new Promise(resolve => setTimeout(callback, time))
}
sleep(3000, () => {
    console.log(`sleep exe ending!`)
})
三、第三种方式:使用data+循环
function sleep(time) {
    const startDate = new Date().getTime()
    while(new Date().getTime() - startDate < time) {}
}
sleep(3000)
console.log(`sleep exe ending!`)
33.如何准确判断一个变量是数组类型?
console.log(arr instanceof Array);
34.从输入url到得到html的详细过程?

1、输入网址
2、DNS解析
3、建立tcp连接
4、客户端发送HTPP请求
5、服务器处理请求 
6、服务器响应请求
7、浏览器展示HTML
8、浏览器发送请求获取其他在HTML中的资源。

35.在js中0.1+0.2等于多少?如何让它得到正确答案?

等于0.30000000000000004,原因是因为浮点数运算中产生的误差
解决:

function add(param1, param2) {
	return parseFloat((param1 + param2).toFixed(10));
}
add(0.1, 0.2);  // 0.3
36.js实现九九乘法表?
for(var i = 1; i <= 9; i++){
	var str = '';
	for(var k = 1; k <= 9; k++){
		if(i >= k){
			str += k + 'x' + i + '=' + i*k + ' ';
		}
	}
	console.log(str)
}
37.什么是构造函数?与普通函数有什么区别?

构造函数:是一种特殊的方法、主要用来创建对象时初始化对象,总与new运算符一起使用,创建对象的语句中构造函数的函数名必须与类名完全相同
与普通函数相比只能由new关键字调用,构造函数是类的标识

38.什么是回调地狱,怎么解决回调地狱?

由于回调地狱是异步的,每一层的回调函数都需要依赖上一层的回调执行完,所有形成了层层嵌套的关系,最终形成了回调地狱。例如:定时器种再写定时器再写定时器,这种就形成了回调地狱
解决办法:
1、避免函数的嵌套
2、模块化开发
3、使用Promise解决

39.说出以下代码i的值?以及怎么才能正确输出0-9?
for(var i=0;i<10;i++){
setTimeout(()=>{
	console.log(i)
},0)
}
//输出10个10
/*如何正确输出0-1*/
第一种:
将var改成let
第二种:采用函数自调的方式
for(var i=0;i<10;i++){
	(function(k){
		setTimeout(()=>{
			console.log(k)
		},0)
	})(i)
}
40.filter和some的区别?

some:用于检测数组中的元素是否满足指定条件(函数提供)有则返回true
filter:用于筛选指定数组中满足指定条件的元素作为新的数组返回

41、数组去重的几种方式?
1、利用数组的indexOf方法去重
 var arr =[1,-5,-4,0,-4,7,7,3];
 function unique(arr){
    var arr1 = [];       // 新建一个数组来存放arr中的值
    for(var i=0,len=arr.length;i<len;i++){
        if(arr1.indexOf(arr[i]) === -1){
            arr1.push(arr[i]);
        }
   }
   return arr1;
}
console.log(unique(arr));    // 1, -5, -4, 0, 7, 3


2、利用ES6 Set()去重
function dedupe(array){
 return Array.from(new Set(array));
}
dedupe([1,1,2,3]) //[1,2,3]


3、sort 方法排序后去重
var arr = [1, 2, 4, 3, 3, 3, 2, 1].sort()
 function sortRepeat() {
     for (let i = 0; i < arr.length; i++) {
          if (arr[i] == arr[i + 1]) {
              arr.splice(i, 1)
              i--
          }
      }
      return arr
  }
42、简述同步和异步的区别

"同步模式"就是后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。

“异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

异步运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列”(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步

43、使用递归完成1到100的累加
function sum(num) {
if( num==1 ){
return 1;
}
return num+sum(num-1);
}
console.log(sum(100))
44、Javascript有哪几种数据类型

1、 值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
2、引用数据类型:对象(Object)、数组(Array)、函数(Function)。

45、写一个function ,清除字符串前后的空格
function trim(str) {
    if (str && typeof str === "string") {
        return str.replace(/(^\s*)|(\s*)$/g,""); //去除前后空白符
    }
}
46、typeof()和instanceof()的用法区别

1、typeof用以获取一个变量或者表达式的类型,typeof一般只能返回如下几个结果:number,boolean,string,function(函数),object(NULL,数组,对象),undefined。

2、instanceof用于判断一个变量是否某个对象的实例,如:
var a=new Array();
alert(a instanceof Array);会返回true

47、prototype 和 proto 区别是什么?

prototype和proto区别在于:prototype是每个函数都会具备的一个属性,它是一个指针,指向一个对象,只有函数才有。而proto是主流浏览器上在除null以外的每个对象上都支持的一个属性,它能够指向该对象的原型。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端阿皓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值