IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 前端校招面试问题总结(JavaScript篇) -> 正文阅读

[JavaScript知识库]前端校招面试问题总结(JavaScript篇)

题目是我从网上找的,找了些答案,主要给自己做一个笔记。

一共有33道题,关于JavaScript的。


一、JavaScript

1. 原始值和引用值类型及区别

答:

原始值: 存储在栈中的简单数据段,即他们的值直接存储在变量访问的位置。
包括五种原始类型:undefined、null、boolean、number、string。

引用值:存储在堆中的对象,即存储在变量处的值是一个指针,只想存储对象的内存处。
包括:object、array、function等

两者的区别
原始变量及他们的值储存在栈中,当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始变量互不影响。

引用值是把引用变量的名称储存在栈中,但是把其实际对象储存在堆中,且存在一个指针由变量名指向储存在堆中的实际对象,当把引用对象传递给另一个变量时,复制的其实是指向实际对象的指针,此时两者指向的是同一个数据,若通过方法改变其中一个变量的值,则访问另一个变量时,其值也会随之加以改变;但若不是通过方法而是通过重新赋值,此时,相当于重新开了一个房间,该值的原指针改变,则另外一个值不会随他的改变而改变。

2. 判断数据类型typeof、instanceof、Object.prototype.toString.call()、constructor

答:

3. 类数组与数组的区别与转换

答:

相同点:都可用下标访问每个元素,都有length属性。

不同点:数组对象的类型是Array,类数组对象的类型是object,也就是说类数组原型是Object;类数组不具有数组所具有的方法,数组遍历可以用 for in和for循环,类数组只能用for循环遍历。

常见的类数组有: 函数的参数 arguments, DOM 对象列表(比如通过 document.querySelectorAll 得到的列表), jQuery 对象 (比如 $(“div”)).

类数组与数组的转化




数组转变成类数组:

var arr = [1, 2, 3, 4];
var obj = { };
[ ].push.apply(obj, arr);
console.log(obj);
输出为原型为Object 的一个对象

类数组转换为数组:

方法一:Array.prototype.slice.call(arrayLike, start);

方法二: Array.from(arrayLike);

Array.from()是ES6中新增的方法,可以将两类对象转为真正的数组:类数组对象和可遍历(iterable)对象(包括ES6新增的数据结构Set和Map)。

4. 数组的常见API

答:

1.reverse()

2.sort()

3.concat()

4.slice()

5.splice()

6.indexOf()、lastIndexOf()

7.join()

5. bind、call、apply的区别

答:

????????三者都是用于改变函数体内this的指向,但是bind与apply和call的最大的区别是:bind不会立即调用,而是返回一个新函数,称为绑定函数,其内的this指向为创建它时传入bind的第一个参数,而传入bind的第二个及以后的参数作为原函数的参数来调用原函数。

????????apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向);apply和call的调用返回函数执行结果;

  如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部按顺序列举出来;

6. new的原理

答:

1.new关键字会首先创建一个空对象
2.将这个空对象的原型对象指向构造函数的原型属性,从而继承原型上的方法
3.将this指向这个空对象,执行构造函数中的代码,以获取私有属性
4.如果构造函数返回了一个对象res,就将该返回值res返回,如果返回值不是对象,就将创建的对象返回

7. 如何正确判断this?

答:

????????要判断this指向哪里,我们必须理解每个函数的this并不是在声明时就被绑定的,而是在调用时被绑定。

8. 闭包及其作用

答:

闭包其实就是「函数」和「函数内部能访问到的变量」(也叫环境)的总和。

闭包的作用:

1.可以间接调用函数内部的局部变量。
2.可以让这些变量的值始终保持在内存中。(因此要注意不能滥用闭包)
3.可以暂存数据,给变量开辟私密空间,避免外部污染。

9. 原型和原型链

答:

????????Javascript对象都有一个叫做原型的公共属性,属性名是_proto_。这个原型属性是对另一个对象的引用,通过这个原型属性我们就可以访问另一个对象所有的属性和方法。

????????每一个实例对象都有一个私有属性_proto_,指向它的构造函数的原型对象(prototype)。原型对象也有自己的_proto_,层层向上直到一个对象的原型对象为null。这一层层原型就是原型链

10. prototype与__proto__的关系与区别

答:?

????????几乎所有的函数(除了一些内建函数)都有一个名为prototype(原型)的属性,这个属性是一个指针指向一个对象,而这个对象的用途是包含可以有特定类型的所有实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的原型对象。(ps:这玩意儿是只有函数特有的属性)

????????对象具有属性__proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。

11. 继承的实现方式及比较

答:

1、原型链继承

//父类,带属性 
function Super(){  
    this.flag = true;  
}  
//为了提高复用性,方法绑定在父类原型属性上  
Super.prototype.getFlag = function(){  
    return this.flag;  
}  
//来个子类  
function Sub(){  
    this.subFlag = false;  
}  
//实现继承  
Sub.prototype = new Super;  
//给子类添加子类特有的方法,注意顺序要在继承之后  
Sub.prototype.getSubFlag = function(){  
    return this.subFlag;  
}  
//构造实例  
var es5 = new Sub;  
  特点:
  1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
  2. 父类新增原型方法/原型属性,子类都能访问到

  缺点:
  来自原型对象的引用属性是所有实例共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上。

2、构造函数继承

  在构造子类构造函数时内部使用call或apply来调用父类的构造函数

  核心:使用父类的的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
function Super(){  
    this.flag = true;  
}  
function Sub(){  
    Super.call(this)  //如果父类可以需要接收参数,这里也可以直接传递  
}  
var obj = new Sub();  
obj.flag = flase;  
var obj_2 = new Sub();  
console.log(obj_2.flag)  //依然是true,不会相互影响  
  优缺点:实现了属性的私有化,但是子类无法访问父类原型上的属性。

  特点:
  1. 解决了1中,子类实例共享父类引用属性的问题
  2. 创建子类实例时,可以向父类传递参数
  3. 可以实现多继承(call多个父类对象)
  缺点:
  1. 实例并不是父类的实例,只是子类的实例
  2. 只能继承父类的实例属性和方法,不能继承原型属性/方法
  3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

3、组合继承

利用构造函数和原型链的方法,可以比较完美的实现继承
function Super(){  
    this.flag = true;  
}  
Super.prototype.getFlag = function(){  
    return this.flag;     // 继承方法  
}  
function Sub(){  
    this.subFlag = flase  
    Super.call(this)    // 继承属性  
}  
Sub.prototype = new Super;  
var obj = new Sub();  
// Sub.prototype = new Super; 会导致Sub.prototype的constructor指向Super;
// 然而constructor的定义是要指向原型属性对应的构造函数的,Sub.prototype是Sub构造函数的原型,
// 所以应该添加一句纠正:Sub.prototype.constructor = Sub;
Sub.prototype.constructor = Sub;  // 修复构造函数指向
Super.prototype.getSubFlag = function(){  
    return this.flag;  
}  
特点:
1. 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
2. 既是子类的实例,也是父类的实例
3. 不存在引用属性共享问题
4. 可传参
5. 函数可复用
缺点:
1. 子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上 的那一份屏蔽了子类原型上的。如图,sub又在constructor里面嵌套了一层

4、寄生组合继承

通过借用构造函数来继承属性;
通过原型链来继承方法。
不必为了指定子类型的原型而调用超类型的构造函数,
function inheritPrototype(subType, superType){
    var protoType = Object.create(superType.prototype);    //创建对象
    protoType.constructor = subType;                    //增强对象
    subType.prototype = protoType;                        //指定对象
}
function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
}

function SubType(name, age){
    SuperType.call(this, name);  
    
    this.age = age;
}
inheritPrototype(SubType, SuperType)
SubType.prototype.sayAge = function(){
    alert(this.age);
}

var instance = new SubType("Bob", 18);
instance.sayName();
instance.sayAge();
inheritPrototype函数接收两个参数:子类型构造函数和超类型构造函数。

创建超类型原型的副本。
为创建的副本添加constructor属性,弥补因重写原型而失去的默认的constructor属性
将新创建的对象(即副本)赋值给子类型的原型
这种方法只调用了一次SuperType构造函数,instanceof 和isPrototypeOf()也能正常使用。

12. 深拷贝与浅拷贝

答:

浅拷贝概念: 对于字符串类型,浅拷贝是对值的复制,对于对象来说,浅拷贝是对对象地址的复制, 也就是拷贝的结果是两个对象指向同一个地址

深拷贝概念: 深拷贝开辟一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

13. 防抖和节流

答:

函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

14. 作用域和作用域链、执行期上下文

答:

一、作用域

在 JavaScript 中, 作用域(scope,或译有效范围)就是变量和函数的可访问范围,即作用域控制着变量和函数的可见性生命周期

1、全局作用域

(1)不在任何函数内定义的变量就具有全局作用域。

(2)实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性

(3)window对象的内置属性都拥有全局作用域,例如 window.name、window.location、window.top 等。

2、局部作用域

(1)JavaScript的作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,称为函数(局部)作用域

3、块级作用域

? ? ? ?块级作用域指在If语句,switch语句,循环语句等语句块中定义变量,这意味着变量不能在语句块之外被访问

二、作用域链

(1)在JavaScript中,函数也是对象,对象中有些属性我们可以访问,但有些不可以(访问),这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。

(2)[[scope]]指的就是我们所说的作用域,其中存储了执行上下文的集合。

(3)[[scope]]中所存储的执行上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

三、执行上下文

(1)当函数执行时,会创建一个称为执行上下文的内部对象(可理解为作用域,不是前面讨论的上下文)。一个执行上下文定义了一个函数执行时的环境

(2)函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文。

(3)当javascript代码文件被浏览器载入后,默认最先进入的是一个全局的执行上下文。当在全局上下文中调用执行一个函数时,程序流就进入该被调用函数内,此时引擎就会为该函数创建一个新的执行上下文,并且将其压入到执行栈顶部(作用域链)。浏览器总是执行位于执行栈顶部的当前执行上下文,一旦执行完毕,该执行上下文就会从执行栈顶部弹出,并且控制权将进入其下的执行上下文。这样,执行栈中的执行上下文就会被依次执行并且弹出,直到回到全局的执行上下文。

15. DOM常见的操作方式

答:

  1. 查找节点
  2. 新建节点
  3. 添加新节点
  4. 删除节点
  5. 设置样式

16. Array.sort()方法与实现机制

答:

该排序方法每个浏览器中实现的都不太一样

chrome 目前采用快排(QuickSort)和插入排序(InsertaionSort),而对于火狐,它采用归并排序(MergeSort)。而IE使用快排。

17. Ajax的请求过程

答:

1.创建Ajax核心对象XMLHttpRequest

2.向服务器发送请求

注意一:open 的参数要牢记,很多面试官爱问这样的细节

  • method:请求的类型;GET 或 POST
  • url:文件在服务器上的位置,相对位置或绝对位置
  • async:true(异步)或 false(同步)
  • 为什么使用 Async=true ?

注意二:post请求不同于get请求

send(string)方法post请求时才使用字符串参数,否则不用带参数。

注意三:post请求一定要设置请求头的格式内容

3.服务器响应处理

3.1 同步处理

3.2 异步处理

18. JS的垃圾回收机制

答:

JS会在创建变量时自动分配内存,在不使用的时候会自动周期性的释放内存,释放的过程就叫 "垃圾回收"。这个机制有好的一面,当然也也有不好的一面。一方面自动分配内存减轻了开发者的负担,开发者不用过多的去关注内存使用,但是另一方面,正是因为因为是自动回收,所以如果不清楚回收的机制,会很容易造成混乱,而混乱就很容易造成"内存泄漏".由于是自动回收,所以就存在一个 "内存是否需要被回收的" 的问题,但是这个问题的判定在程序中意味着无法通过某个算法去准确完整的解决,后面探讨的回收机制只能有限的去解决一般的问题。

垃圾回收对是否需要回收的问题主要依赖于对变量的判定是否可访问,由此衍生出两种主要的回收算法:

  • 标记清理
  • 引用计数

标记清理

标记清理是js最常用的回收策略,2012年后所有浏览器都使用了这种策略,此后的对回收策略的改进也是基于这个策略的改进。其策略是:

  1. 变量进入上下文,也可理解为作用域,会加上标记,证明其存在于该上下文;
  2. 将所有在上下文中的变量以及上下文中被访问引用的变量标记去掉,表明这些变量活跃有用;
  3. 在此之后再被加上标记的变量标记为准备删除的变量,因为上下文中的变量已经无法访问它们;
  4. 执行内存清理,销毁带标记的所有非活跃值并回收之前被占用的内存;

引用计数

引用计数策略相对而言不常用,因为弊端较多。其思路是对每个值记录它被引用的次数,通过最后对次数的判断(引用数为0)来决定是否保留,具体的规则有

  • 声明一个变量,赋予它一个引用值时,计数+1;
  • 同一个值被赋予另外一个变量时,引用+1;
  • 保存对该值引用的变量被其他值覆盖,引用-1;
  • 引用为0,回收内存;

19. JS中的String、Array和Math方法

答:

1、math函数

2、array函数

?3、string函数

20. addEventListener和onClick()的区别

答:

1.onclick事件在同一时间只能指向唯一对象

2.addEventListener给一个事件注册多个listener

3.addEventListener对任何DOM都是有效的,而onclick仅限于HTML

4.addEventListener可以控制listener的触发阶段,(捕获/冒泡)。对于多个相同的事件处理器,不会重复触发,不需要手动使用removeEventListener清除

5.IE9使用attachEvent和detachEvent

21. new和Object.create的区别

答:

太难复制了,想了解的点这个链接吧

22. DOM的location对象

答:

Location 对象包含有关当前 URL 的信息。

Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问。

Location 对象描述

Location 对象存储在 Window 对象的 Location 属性中,表示那个窗口中当前显示的文档的 Web 地址。它的?href 属性存放的是文档的完整 URL,其他属性则分别描述了 URL 的各个部分。这些属性与 Anchor 对象(或 Area 对象)的 URL 属性非常相似。当一个 Location 对象被转换成字符串,href 属性的值被返回。这意味着你可以使用表达式 location 来替代 location.href。

不过 Anchor 对象表示的是文档中的超链接,Location 对象表示的却是浏览器当前显示的文档的 URL(或位置)。但是 Location 对象所能做的远远不止这些,它还能控制浏览器显示的文档的位置。如果把一个含有 URL 的字符串赋予 Location 对象或它的 href 属性,浏览器就会把新的 URL 所指的文档装载进来,并显示出来。

除了设置 location 或 location.href 用完整的 URL 替换当前的 URL 之外,还可以修改部分 URL,只需要给 Location 对象的其他属性赋值即可。这样做就会创建新的 URL,其中的一部分与原来的 URL 不同,浏览器会将它装载并显示出来。例如,假设设置了Location对象的?hash 属性,那么浏览器就会转移到当前文档中的一个指定的位置。同样,如果设置了?search 属性,那么浏览器就会重新装载附加了新的查询字符串的 URL。

除了 URL 属性外,Location 对象的?reload() 方法可以重新装载当前文档,replace()?可以装载一个新文档而无须为它创建一个新的历史记录,也就是说,在浏览器的历史列表中,新文档将替换当前文档。

23. 浏览器从输入URL到页面渲染的整个流程(涉及到计算机网络数据传输过程、浏览器解析渲染过程)

答:

  • 1、输入地址
  • 2、浏览器查找域名的 IP 地址
  • 3、浏览器向 web 服务器发送一个 HTTP 请求
  • 4、服务器的永久重定向响应
  • 6、服务器处理请求
  • 7、服务器返回一个 HTTP 响应
  • 8、浏览器显示 HTML
  • 9、浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)

24. 跨域、同源策略及跨域实现方式和原理

答:

同源策略是对Javascript代码能对哪些web页面进行操作的一条完整安全限制。具体来说,脚本只能读取和所属文档来源相同的窗口和文档属性。

文档的来源包括了协议,主机,以及载入文档的端口。从不同的web服务器载入的文档具有不同的来源。通过通统一主机不同端口的文档也有不同的来源。http和https也有不同的来源。

注意。脚本本身的来源并不重要,重要的是嵌入的界面的来源。

假设一个来自A的脚本被以<script>标签的方式引用到的B的一个web页面中,那么他就可以完整访问这个web页面的文档内容。当脚本打开了另一个来自B 的web页面,他依然可以完整访问这个页面的文档内容,但若是打开C(A也可以),同源策略就会发生作用,阻止访问。

解决方法一:

跨域资源共享: 使用新的请求头Origin和响应头Access-Control-Allow-Origin,他允许服务器显式的列出源,或使用通配符来匹配所有源并允许由任何地址请求文件。

实现方式:

前端不用动,发出一个普通的ajax请求,浏览器会自动加上Origin请求头

后端要设置一个响应头 Access-Control-Allow-Origin:* 这样就可以了

CORS分为两种情况,分为简单请求和非简单请求

对于简单请求

浏览器直接发出CORS请求,即在头部自动加上origin字段,说明来自哪个源(协议 + 域名 + 端口)。

服务器返回一个添加了几个头部信息字段的HTTP Response说明是否可以同意本次请求。其中带有Access-Control-Allow-Origin字段说明指定了允许访问该资源的外域URI(带有通配符*说明允许来自所有域的请求)。如Access-Control-Allow-Origin字段不匹配或是不包含该字段,浏览器则会抛出一个错误,被XMLHttpRequestonerror回调函数捕获。(注意:不能通过HTTP Response的状态码来识别)

对于非简单请求

浏览器会自动使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。该预检请求中包含有origin、Access-Control-Request-Method、Access-Control-Request-Headers分别说明源站URI、实际请求的方法、实际请求所携带的首部字段。

服务器收到预检请求后检查originAccess-Control-Request-MethodAccess-Control-Request-Headers字段后,回复一个带有Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers说明服务器对应允许跨域访问的URI、请求方法以及请求头部字段。 服务器通过了"预检"请求之后,基本和简单请求一样。浏览器每次请求带上origin字段,服务器回应带上Access-Control-Allow-Origin

解决方法二 :

JSONP

JSONP的主要原理是,<script>标签不受同源策略影响,可加载异域服务器上的js脚本以执行。利用该原理,后端将数据封装成一句js执行语句(函数执行语句)。前端在加载执行该语句时,调用预先声明好的函数,即可完成对数据的处理。

JSONP 只适用于 get

JSONP 实现

//假设后端规定好了包裹的函数名字就叫callback
function getJSONP(url,callback) {
    var script = document.createElement('script')
    getJSONP['callback'] = function(response){
        try{
            callback(response)
        }
        finally{
            delete getJSONP['callback']
            script.parentNode.removeChild(script)
        }
    }
    script.src = url
    script.parentNode.appendChild(script)
}

25. 浏览器的回流(Reflow)和重绘(Repaints)

答:

1、回流 (Reflow)

????????当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流

会导致回流的操作

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见DOM元素
  • 激活CSS伪类(例如::hover
  • 查询某些属性或调用某些方法

一些常用且会导致回流的属性和方法

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

2、重绘 (Repaint)

????????当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

26. JavaScript中的arguments

答:

????????arguments 是一个类数组对象。代表传给一个function的参数列表。

27. EventLoop事件循环

答:

这个题挺复杂的,想看具体的可以点这个链接:

JavaScript中的Event Loop(事件循环)机制

28. 宏任务与微任务

答:

1、宏任务

(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。

浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:

(macro)task->渲染->(macro)task->...

宏任务包含:

script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)

2、微任务

microtask,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。

所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。

微任务包含:

Promise.then
Object.observe
MutationObserver
process.nextTick(Node.js 环境)

29. BOM属性对象方法

答:

这个很长哦!点击这个链接:JavaScript BOM浏览器对象模型

30. 函数柯里化及其通用封装

答:

柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

举个例子:

function add(a, b) {
    return a + b;
}

// 执行 add 函数,一次传入两个参数即可
add(1, 2) // 3

// 假设有一个 curry 函数可以做到柯里化
var addCurry = curry(add);
addCurry(1)(2) // 3

首先记住一句话 函数柯里化,其实就是把多次调用的变量保存在闭包中,每次调用都查看一下变量数和原函数的形参数量是否相等。不相等就继续递归。直到相等为止就处理了。

函数柯里化实现

function curry(fn,args){
    var length = fn.length // 获得fn应有的形参数量

    var arg = args || [] // 如果初始变量有传进去就用初始变量作为初始值,不然就是空数组,用于收集后续调用的变量

    return function(){
        var _arg = arg.slice(0) // 外面变量的副本
            //  循环的是return 的这个funciton的传入实参的长度
        for(var i =0 ;i<arguments.length;i++){
            // 把变量全部传入这个存储总变量的副本中

            _arg.push(arguments[i])
        }
        //如果小于说明还没达到理想的参数数量,继续柯里化等待下一轮参数
        if(_arg.length<length){
            return curry.call(this,fn,_arg) // 这个设置this是因为如果以后有对象进行调用的能指向对象的内部,不然就指向window了
        }else{
            return fn.apply(this._arg) // 执行原函数
        }
    }
}

高颜值方法:

const currying = (fn) => {
    judge = (...args) => {
        fn.length = args.length ?
            fn(args) : 
            (arg) => judge(...args,arg)
    }
}

31. JS的map()和reduce()方法

答:

1、map

举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个数组[1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map实现如下:

map

由于map()方法定义在JavaScript的Array中,我们调用Arraymap()方法,传入我们自己的函数,就得到了一个新的Array作为结果:

'use strict';

function pow(x) {
    return x * x;
}

?

注意:map()传入的参数是pow,即函数对象本身。

你可能会想,不需要map(),写一个循环,也可以计算出结果:

var f = function (x) {
    return x * x;
};

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
for (var i=0; i<arr.length; i++) {
    result.push(f(arr[i]));
}

的确可以,但是,从上面的循环代码,我们无法一眼看明白“把f(x)作用在Array的每一个元素并把结果生成一个新的Array”。

所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把Array的所有数字转为字符串:

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']

2、reduce

再看reduce的用法。Array的reduce()把一个函数作用在这个Array[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

比方说对一个Array求和,就可以用reduce实现:

var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x + y;
}); // 25

要把[1, 3, 5, 7, 9]变换成整数13579,reduce()也能派上用场:

var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x * 10 + y;
}); // 13579

32. “==”和“===”的区别

答:

????????“==” 运算符会在进行相等比较之前会进行必要值的类型转换。简单来说,就是先把值转换为一样的类型再进行相等比较。就算比较的值的类型不相同,也可以通过强制转换类型成一样的,不会发生错误。

????????“===” 运算符,它不会执行类型转换,因此如果两个值不是相同类型,那么当比较时,它将返回false。如果比较两个变量,它们的类型彼此不兼容,则会产生编译错误。

33. setTimeout用作倒计时为何会产生误差?

答:

????????setTimeout作为异步任务,在实现倒计时功能的时候,除了执行我们功能的实现代码,还会有主线程对任务队列的读取及执行等过程,这些过程也需要耗费一些时间,所以会因为event loop的机制出现些许误差。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-25 08:01:50  更:2021-11-25 08:03:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 4:22:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码