前端面试题js总结

实现JavaScript继承

原型链继承: 这招有点粗糙,适合对象简单的情况。就像大家共用一把刷子一样,得注意别乱动,不然会影响其他人。

构造继承: 挺直截了当的,通过在子类构造函数中调用父类构造函数。不过有点不足,父类原型上的方法没法继承。

实例继承: 就是把父类实例当成子类的“学习资料”。方便点,可以调用父类方法,但也只能是“实例方法”。

拷贝继承: 这就有点暴力,直接把父类的东西都拷贝给子类。适合小规模的数据,不过得当心点,别搞得太乱。

组合继承: 感觉这一招比较全面,结合了构造继承和原型链继承的优点。避免了一些坑,有点像两全其美的感觉。

寄生组合继承: 这是优化过的组合继承,避免了一些不必要的麻烦。有点像是组合继承的进化版。

instanceof的原理是什么

有个对象,你想知道它是不是某个类型的。那就得查查它的“家谱”,也就是原型链。你瞅瞅这个对象的祖宗是谁,往上追溯到底能不能找到那个类型的“族谱”(也就是prototype)。

如果你追溯到头都找不到,那这个对象就不是那个类型的实例。反之,如果找到了,那就说明这个对象是那个类型的后代。就这么简单,就像查家谱一样,得一级一级往上翻,看看是不是同一家的。

请描述一下 cookies,sessionStorage 和 localStorage 的区别?

1.Cookies(饼干): 想象一下你在网上逛街,看中了一些商品,你把它们放进购物车,这个购物车就像是一盒饼干,可以一会儿关了网页再打开,饼干还在那里。Cookies就是这样,它可以存储小段的信息,而且在不同的页面和不同的浏览器之间都能共享。不过,饼干有个问题,就是每次发请求的时候,饼干都会被带上,有点像是带了个标签,有时候可能会有点“沉”。
2.sessionStorage(会话存储): 想象一下你在玩一个网页游戏,游戏刷新了一下,但是你的分数没了。这就是sessionStorage,它是短期记忆,只在当前会话(也就是你打开的这个页面)有效。刷新页面的话,它就忘了,就像你玩游戏忘掉上一关的得分了一样。
3.localStorage(本地存储): 现在,想象一下你写了一个日记,关了网页再打开,你的日记还在。这就是localStorage,它是长期记忆,数据可以一直保存在你的电脑上,就像是一个小保险柜。不过要小心,因为这个保险柜是不分会话的,删了浏览器的历史数据,它也可能跟着没了。

所以,cookies是个饼干,一直带着;sessionStorage像是短期记忆,只记得当前事情;localStorage是长期记忆,像是小保险柜,数据一直在那儿。希望这样子理解更清楚!存储大小

a 标签中,如何禁用 href 跳转页面或定位链接?

onclick="return false;"
onclick="ds(event)"

<a href="#" onclick="return false;">return false;</a>
<a href="http://www.baidu.com" onclick="ds(event)">baidu</a>
<script>
    function ds(e){
        e.preventDefault();
    }
</script>

为什么 await 在 forEach 中不生效?如何解决?

在 forEach 里面使用 await 的时候,它好像没啥用,因为 forEach 不太懂得等待。

看,你有一堆任务要处理,就像一群小伙伴排队等你点名一样。但 forEach 就是个有点急性子的队伍,你让它们等等,它偏不肯。所以,你在 forEach 里用了 await,可这一伙小伙伴全都跑到前面去了,根本没等你点名完。

解决方案呢,就是换个听话的队伍,比如说 for...of 或者 map。这些队伍听你的,遇到 await 就老老实实等着。就好像你点名,他们一个个站好,等你慢慢来,不插队。所以,别用 forEach,选个听话的队伍,你的 await 就能生效了!

是否所有函数都有 prototype 一说?

箭头函数没有
使用Function.prototype.bind创建的函数对象没有

简述原生 js 发 ajax 的步骤

当你想要用原生的 JavaScript 来发送 AJAX 请求的时候,其实就像你给朋友发一条短信一样。下面是一种口语化的描述:
首先,你要拿出你的手机,也就是创建一个 XMLHttpRequest(XHR)对象,就像打开短信APP一样。然后,你得设置这条短信的内容和目的地。在XHR对象上设置一些东西,比如URL(目的地)和请求方法(GET、POST之类的)就像写收件人和编辑短信内容。
接下来,你得告诉你的朋友,“嘿,我准备好了,你可以发送了!”也就是用XHR对象的send()方法发送这条短信。等着,等着,有时候可能要等一段时间才能收到回复。
最后,当你收到朋友的回复,也就是服务器返回的数据,你要做些什么就看你的需求了。可能是显示在页面上,或者做些其他处理。就像你收到朋友的回复,你可以看看内容,然后决定怎么回应。
这样描述的话,就是用手机发短信,等回复,然后看看回复的内容,做相应的处理。希望这样描述能让你更容易理解用原生 JavaScript 发送 AJAX 请求的过程!

ts 和 js 的区别

嘿,JS和TS其实就像是两个兄弟,有点像巧克力冰淇淋和草莓冰淇淋的区别。让我给你聊聊:
首先,JS(JavaScript)就像是那个传统的巧克力冰淇淋,一开始大家都很喜欢,但有时候你吃多了可能会觉得有点太甜,有点不够健康。
然后,TS(TypeScript)就是像草莓冰淇淋一样的升级版。TS不仅有JS所有的甜蜜,还多了点果味。具体来说,TS是在JS的基础上加了点类型的概念,就像是在草莓冰淇淋里多了些草莓块。
这个类型的概念就是让你在写代码的时候更有条理,不容易搞混。有时候,你写了一堆代码,等运行的时候才发现有个地方写错了,就像是吃了块不好吃的冰淇淋,有点失望。TS帮你避免了这种情况,提前告诉你哪里有问题。
总的来说,JS是传统的、甜蜜的冰淇淋,而TS是升级版,加了点类型的草莓味。两者都有各自的优点,就看你喜欢哪种口味啦!

你了解原型链吗 你能说说 prototype 与 proto 的区别吗

当谈到原型链,就像是玩传话游戏一样。
首先,prototype就像是一个祖传的本子,里面有你家族的秘密配方。这个东西是函数特有的,就像是你家的传家宝,用来创建新对象时可以继承这些“秘密”。
然后,proto就像是一个小纸条,上面写着“谁是你的爸爸”。这个东西是每个对象特有的,告诉你对象的父亲是谁。也就是说,它指向了创建这个对象的函数的prototype。
所以说,prototype是函数的东西,是用来创建新对象的特殊秘籍;而proto是对象的东西,告诉你它的“家世”。这俩东西都在帮助建立那个有趣的东西叫做原型链,就像是家谱一样,把一代又一代的对象联系在一起。

你知道什么是原型吗?我们为什么要用原型呢?或者说原型为我们提供了什么?

嘿,当谈到原型的时候,就像在说我们的编程世界里的“祖传秘籍”。
原型就好比是一个蓝图,告诉了你的对象应该是什么样子,有什么特殊技能。它就像是一张指南,告诉你的编程小伙伴们:“嘿,我们这个家族有个传统,都要有这个样子,有这些本领。”
为啥我们要用原型呢?想象一下,你有一堆相似的东西要做,比如一群小怪兽要创建,它们都有一些共同的特征和技能。你不想一个个重头创建,那太累了。原型就是告诉你,创建一个新的小怪兽,不用从头开始,直接按照这个蓝图来,省事又方便。
原型给我们提供了一种轻松创建和共享代码的方式,就像是告诉你如何制作一道传家菜谱一样。这样,我们就能更高效地写代码,而且新创建的对象还能和原型分享一些功能,就好比新一代也能继承家族传统技能。所以,原型不仅省事,还能让我们的代码更有组织、更易维护。

简述 src 和 href 的区别?

嘿,src和href就像是两个不同的引路标。
首先,src(source)是用来告诉浏览器:“嘿,这里有个东西得加载进来!”比如说,图片、音频或者脚本文件,都是用src来指定的。就像给一个地方打个标记,告诉你要从这儿拿点东西过来。
然后,href(hypertext reference)是给超链接用的,告诉浏览器:“嘿,这是个链接,点击它会带你去另一个地方!”比如说,你点一下页面上的链接,它就会带你到另一个页面或者资源。就像给你指一条路,告诉你怎么到达下一个地方。
总的来说,src是用来加载东西,比如图片、脚本之类的;而href是用来告诉你怎么去别的地方,就像是页面上的链接。两者都是帮助我们在网页世界里找到我们想要的东西或者去往想去的地方的引路标!

js中的常用事件绑定方法

嗨!JS里常用的事件绑定方法就像是给网页添加各种酷炫功能的神奇方式。
首先,我们有addEventListener。这个家伙就像是给你的元素贴上“耳朵”,它能听到各种事件,比如点击、鼠标移动、键盘敲击等等。你可以告诉它:“嘿,如果有人点了这个按钮,就跟我说一声!”然后你就能在按钮被点击时执行一些操作。
其次,还有onclick这样的老方法。这个家伙就像是直接把事件黏在元素上,比如说你可以在一个按钮上写上onclick="doSomething()",意思是点击这个按钮的时候就执行doSomething()函数。
还有其他类似的方法,比如onmouseover(鼠标移过去时触发)或者onkeyup(按键被按下并松开时触发)等等,它们就像是元素自带的“魔法指令”,告诉你在什么情况下触发某个操作。
总的来说,这些事件绑定方法就是让你的网页元素具备了与用户交互的能力,让用户点击、输入或者移动鼠标的时候,网页可以做出相应的反应,变得更有趣、更有动态性!

插入几万个 dom ,如何实现页面不卡顿?

通过分批次异步插入大量数据到页面中。它设定了总数据量和每次插入的数据条数,然后利用 `requestAnimationFrame` 实现异步循环插入,避免一次性插入大量数据造成页面性能问题。每次循环内部创建文档片段,并将一定数量的 `li` 元素批量添加到文档片段中,最终通过 `appendChild` 将文档片段添加到页面。

为什么操作 dom 慢?

嘿,DOM操作有时候就像是在找东西,但是这个找东西有时候比较慢,就好像你找钥匙找了半天还是找不到一样。
首先,DOM是个大家族,你要是去找个特定的元素,有时候得从家里的每个角落一个个摸索。就好比你得找到那个藏在柜子深处的袜子,一样费时间。
其次,每次你动一下DOM,浏览器都要重新计算一下页面上的布局和样式。就像你挪动房间里的一张桌子,整个房间的布局都得重新安排一下,这样就会耗费不少时间。
还有就是频繁的DOM操作,就像是你要是一下子在房间里翻个底朝天,浏览器可能会有点手忙脚乱。频繁操作DOM就相当于不停地给浏览器添乱,它得一直忙碌着应付你的“折腾”。
所以,DOM操作有时候慢,主要是因为它是个大家族,找东西有点费劲;每次操作都得重新计算布局和样式,有点费时;而且频繁操作就像是给浏览器添堵,可能会让它有点不知所措。所以,最好在可能的情况下,尽量减少DOM操作,让浏览器轻松点。

并行和并发的区别是什么?

嘿,并行和并发有点像是在谈论人们同时干活的不同方式。
首先,想象你有两个任务要处理。并发就像是你一个人要同时处理这两件事情,你可能会一会儿做这个,然后转头又处理那个,来回切换,看起来就像是同时在做。
然后,来说说并行。这就像是你有两个好朋友,可以一起帮你完成这两个任务。每个朋友负责一件事,然后他们一起动手,同时做这两个任务,速度更快。
简单说,并发是在一段时间内处理多件事情,有点像来回切换;而并行是真正同时处理多件事情,有点像团队合作一起干活。就好比你一个人能同时吃饭、听音乐,这是并发;但如果你叫上朋友,大家一起做不同的事情,这就是并行了。

介绍一下 ES6 中 Set, Map的区别?

当然可以!ES6中的Set和Map就像是你的工具箱里的两把不同的工具,各有各的特色。
首先,说说Set。Set就像是一个超大的去重工具,你往里塞东西,它自动帮你去掉重复的。就好比你有一袋糖果,你往里放了两颗一样的,Set就会帮你只留下一颗,不重不多。
然后,Map就是一个记事本。你可以把键和值放进去,就像是你有一本地址簿,键是人名,值是他们的地址。这样你想查找某个人的地址的时候,就特别迅速,不用翻整本。
总结一下,Set就是去重大师,让你集合里的东西井然有序;而Map就是你的私人记事本,让你以键值对的方式轻松查找信息。两者都是ES6给我们提供的很实用的工具,让编程变得更加方便。当然可以!ES6中的Set和Map就像是你的工具箱里的两把不同的工具,各有各的特色。
首先,说说Set。Set就像是一个超大的去重工具,你往里塞东西,它自动帮你去掉重复的。就好比你有一袋糖果,你往里放了两颗一样的,Set就会帮你只留下一颗,不重不多。
然后,Map就是一个记事本。你可以把键和值放进去,就像是你有一本地址簿,键是人名,值是他们的地址。这样你想查找某个人的地址的时候,就特别迅速,不用翻整本。
总结一下,Set就是去重大师,让你集合里的东西井然有序;而Map就是你的私人记事本,让你以键值对的方式轻松查找信息。两者都是ES6给我们提供的很实用的工具,让编程变得更加方便。

promise 常见方法和 all 和 race的应用场景

`Promise.race()` 允许多个 Promise 同时执行,当有一个 Promise 完成或拒绝时,整个 `race` 就会结束。它的场景在于设置超时或并发执行多个异步任务,以最快的结果为准。

`Promise.all()` 则是等待所有的 Promise 完成,只有当所有的 Promise 都成功完成时才会返回一个成功结果,否则返回一个失败结果。常用于并行请求多个数据,等待它们都完成后再进行下一步操作。

常见内存泄漏

内存泄漏常见于:

1. 静态集合类和持有长生命周期对象的引用,如HashMap等。长生命周期对象持有短生命周期对象的引用,即使短生命周期对象不再使用,也因为引用关系无法释放,导致内存泄漏。

2. 连接未关闭,比如数据库、网络、IO连接等。如果连接未显式关闭,会导致对象无法被垃圾回收,产生内存泄漏。

3. 变量作用域不合理,变量定义的作用范围大于使用范围,且未及时设置为null,可能引起内存泄漏。

4. 内部类持有外部类对象的引用,导致外部类对象无法被垃圾回收。

5. 修改哈希值,在存储HashSet集合后修改对象的哈希值,导致无法在集合中找到对象。

6. 缓存泄漏,将对象引用放入缓存中并遗忘,解决方式可以使用WeakHashMap代表缓存。

7. 监听器和回调,注册回调但未显式取消,导致回调积聚。使用弱引用的方式保存回调可以解决此问题。

数组去重的方法

方法一:双层循环,外层循环元素,内层循环时比较值如果有相同的值则跳过,不相同则push进数组

方法二:利用splice直接在原数组进行操作,双层循环,外层循环元素,内层循环时比较值
,值相同时,则删去这个值
注意点:删除元素之后,需要将数组的长度也减1.

方法三:利用对象的属性不能相同的特点进行去重

方法四:利用indexOf以及forEach

方法五:利用ES6的set

异步的解决方案有哪些?

1.回调函数callback
2.事件发布订阅
3.Promise
4.Generator
5.async/await

介绍下事件代理,主要解决什么问题

1. 大量事件绑定增加浏览器内存占用,严重影响性能。
2. Ajax引入导致局部刷新,需要重新绑定事件。
3. 部分浏览器在移除元素时,未及时移除绑定的事件,可能导致内存泄漏。
4. Ajax中重复绑定事件造成代码过于耦合,影响后期维护。

JS中的常见设计模式以及应用场景?

1、单例模式
单例模式就是一个实例在整个网页的生命周期里只创建一次,后续再调用实例创建函数的时候,返回的仍是之前创建的实例。在实际开发中应用十分广泛,例如页面中的登录框,显示消息的提示窗
2、策略模式
策略模式是指将策略(算法)封装起来,策略的目的是将算法和使用分离开。
3、代理模式
代理模式很好理解,我们不能直接使用目标函数,而是通过调用代理函数来实现对目标函数的使用。
4、发布订阅模式
发布订阅模式在实际应用中非常常见,例如,我们在微信App上关注了某个公众号,当该公众号有新文章发布时,就会通知我们。
发布订阅模式定义了一种一对多的依赖关系,当“一”发生变化,通知多个依赖。
5、命令模式
所谓命令模式就是将下要执行的业务逻辑封装到一个函数或类中,不需要具体谁来执行该命令的

构造函数、实例对象、原型对象三者的关系是什么?

每个函数(构造函数)都有一个原型对象,可以通过 .prototype 属性访问。
通过 new 关键字创建的实例对象可以访问构造函数的原型对象中的属性和方法。
实例对象有一个内部指针([[Prototype]] 或 __proto__),指向构造函数的原型对象。
构造函数的原型对象上的属性和方法可以被所有实例对象共享,而不是每个实例都拥有一份独立的拷贝,这有助于节省内存空间。

JS的基本数据类型判断有什么方法?

typeof
instanceof
constructor
toString

map、fillter、reduce 各自有什么作用?

1. Map: 生成新数组,遍历原数组的每个元素并对其进行转换后放入新数组。回调函数接收当前元素、索引和原数组作为参数。

2. Filter: 创建新数组,遍历原数组并将返回值为 `true` 的元素添加到新数组中,可用于删除不需要的元素。回调函数同样接收当前元素、索引和原数组作为参数。

3. Reduce: 将数组元素通过回调函数最终转换为一个值。它接受两个参数:回调函数和初始值。回调函数有四个参数:累计值、当前元素、当前索引和原数组。其中累计值是该函数执行的结果,初始值在第一次回调时作为第一个参数传入。

使用箭头函数应该注意什么?

1. 不要在对象里面定义函数,对象里面的行数应该用传统的函数方法
2. 不要在对原型对象上定义函数,在对象原型上定义函数也是遵循着一样的规则
3. 不要用箭头定义构造函数
4. 不要用箭头定义事件回调函数

为什么 JavaScript 是单线程

js作为主要运行在浏览器的脚本语言,js主要用途之一是操作DOM。

举一个栗子,如果js同时有两个线程,同时对同一个dom进行操作,这时浏览器应该听哪个线程的,如何判断优先级?

为了避免这种问题,js必须是一门单线程语言

import export commonJS 对比区别

ES6 模块与 CommonJS 在导入和导出方式上有很多不同:

1. **语法差异**:
   - ES6 模块使用 `import` 和 `export` 关键字来导入和导出模块。
   - CommonJS 使用 `require()` 函数来导入模块,`module.exports` 或 `exports` 导出模块。

2. **运行时加载 vs 编译时加载**:
   - ES6 模块是在代码编译阶段进行静态分析,模块的依赖关系在编译时确定。
   - CommonJS 是在运行时加载,模块的依赖关系在代码执行时动态确定。

3. **模块输出**:
   - ES6 模块的输出是对值的引用,模块之间共享的是原始值的引用,可以动态更新。
   - CommonJS 模块输出的是值的拷贝,模块之间共享的是拷贝的副本,不会动态更新。

4. **上下文差异**:
   - 在 ES6 模块中,`this` 指向 `undefined`,因为 ES6 模块自身就是一个严格模式下的函数。
   - 在 CommonJS 模块中,`this` 指向一个模块对象,通常表示当前模块的导出对象。

这些差异意味着在使用 ES6 模块和 CommonJS 模块时需要注意其运行机制、导入导出方式以及模块间数据共享的方式。

禁止事件冒泡,禁止默认事件

e.stopPropagation();
e.preventDefault();

进程线程区别是什么?

进程和线程的区别体现在以下几个方面:
1.地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。

2.通信:进程间通信IPC(管道,信号量,共享内存,消息队列),线程间可以直接独写进程数据段(如全局变量)来进程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

3.调度和切换:线程上下文切换比进程上下文切换快得多。

4.在多线程OS中,进程不是一个可执行的实体。

Promise 避免回调地狱的语法糖–实现链式调用的核心点是什么?

解决回调地狱的终极方法 async/await ES7的语法,可以通过 async/await让代码看起来像同步的
async异步 await等待
await 等待 就是当后面跟的是promise对象,就让他停止 ,先让里面的异步事情做完,在把结果返回给前面的新变量,在继续向后执行
他只生效当前作用域内部,也就是async函数内部。

实现链式调用的核心点:
在 then 中新创建的 Promise,它的状态变为 fulfilled 的节点是在上一个 Promise的回调执行完毕的时候。也就是说当一个 Promise 的状态被 fulfilled 之后,会执行其回调函数,而回调函数返回的结果会被当作 value,返回给下一个 Promise(也就是then 中产生的 Promise),同时下一个 Promise的状态也会被改变(执行 resolve 或 reject),然后再去执行其回调,以此类推下去…

ES6 箭头函数和普通函数有什么差异?

1. 相比普通函数更简洁的语法
2. 没有this,捕获其所在上下文的 this 值,作为自己的 this 值
3. 不能使用new,箭头函数作为匿名函数,是不能作为构造函数的,不能使用new
4. 不绑定arguments,用rest参数...解决
    let test3=(...a)=>{console.log(a[1])} //22
5. 使用call()和apply()调用:由于 this 已经在词法层面完成了绑定,通过 call() 或 apply() 方法调用一个函数时,只是传入了参数而已,对 this 并没有什么影响:
6. 箭头函数没有原型属性
7. 不能简单返回对象字面量
    let fun5 = ()=>({ foo: x })   //如果x => { foo: x }  //则语法出错
8. 箭头函数不能当做Generator函数,不能使用yield关键字
9. 箭头函数不能换行
    let a = ()
          =>1; //SyntaxError: Unexpected token =>

简述call、apply、bind,call 和 apply哪个性能更好?

1、call()
call() 方法调用一个函数, 其具有一个指定的 this值和分别地提供的参数(参数的列表)。 第一个参数:在 fun 函数运行时指定的 this 值;如果指定了 null 或者 undefined 则内部 this 指向 window,后面的参数:指定的参数列表
2、apply()
apply()方法调用一个函数, 其具有一个指定的 this 值,以及作为一个数组(或类似数组的对象)提供的参数。apply() 与 call() 非常相似,不同之处在于提供参数的方式。apply() 使用参数数组而不是一组参数列表。
3、bind()
bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。
当目标函数被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。绑定函数被调用时,bind() 也接受预设的参数提供给原函数。
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。

/* ------call 和 apply哪个性能更好?------ */
call的性能要比apply好一些,尤其是传递给函数的参数超过3个时所以后期开发的时候,可以使用call多一些
(传参数3个以内的话,call和apply性能差不多,超过3个以上call更好一些)

for-in 循环会遍历出原型上的属性吗?怎么避免遍历到原型上的属性

使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问

只遍历对象自身的属性,而不遍历继承于原型链上的属性,需要使用hasOwnProperty 方法过滤一下。

图片懒加载怎么实现?

原理:随着滚轮滚动,底部的图片会被不断地加载,从而显示在页面上,按需加载,当页面需要显示图片的时候才进行加载,否则不加载

eventloop 渲染在哪一步?

在前端开发中,任务可以分为同步任务和异步任务。同步任务会立即执行,而异步任务会在后台执行,并通过任务队列的机制进行协调。
事件循环是处理这些任务的方式之一,其中有两种任务:宏任务(Macro Task)和微任务(Micro Task)。主线程执行宏任务,每个宏任务结束后都要清空微任务队列。
常见宏任务包括整体脚本、定时器(setTimeout、setInterval)、I/O 操作、UI 交互事件等。微任务主要包括 Promise、MutationObserver、process.nextTick(在 Node.js 环境中)等。
一个事件循环(tick)的执行过程包括选择最先进入队列的宏任务,执行它,然后检查并执行微任务,更新渲染,重复这个过程。
举个例子:当执行整体脚本时,遇到 setTimeout 会将其回调函数放入宏任务队列,遇到 Promise 会将其 then 函数放入微任务队列。然后执行完整体脚本后,先执行微任务队列中的任务,再执行宏任务队列中的任务。这个过程不断循环。
简单来说,事件循环是一种处理同步和异步任务的机制,确保宏任务和微任务按照一定的顺序执行。这样可以保证页面渲染和用户交互的顺畅性。

super() 是否必须执行?不执行怎么让它不报错?

非必须,
在 JavaScript 中,super 指的是父类的构造函数
如果想在构造函数中使用this,你必须首先调用super。 先让父类做完自己的事
不执行无法使用this,
    不报错的方法:
        1:不使用this
        2:手动修正this

什么是函数式编程?什么的声明式编程?

函数式编程注重于将函数作为主要的构建块,可以将函数传递给其他函数,也可以将函数作为返回值。这样的编程方式更注重于“做什么”而非“怎么做”。
声明式编程是一种以数据结构表达程序逻辑的方式,强调告诉计算机要做什么,而不是具体怎么做。SQL语句是声明式编程的例子,它描述了选择满足条件的数据,而不需要指定具体的操作步骤。
总的来说,函数式编程强调函数的重要性和灵活性,而声明式编程注重描述程序的目标而非具体执行步骤。

跨域是什么?有哪些解决跨域的方法和方案?

跨域是指在web开发中,当一个域名的网页通过JavaScript等方式访问另一个域名的资源时,由于浏览器的同源策略(同源是指协议、域名、端口号都相同),会阻止这种跨域请求,以保障用户的安全性。
解决跨域的方法有几种:

1.服务端代理请求: 通过服务器端进行跨域请求,服务器端去获取资源然后返回给客户端。这绕过了浏览器的同源策略。
2.JSONP跨域: 利用script标签的跨域能力,通过在页面中动态创建script标签,将请求放在script的src属性中,返回的数据会作为脚本被执行。需要注意的是JSONP只适用于GET请求。
3.CORS(跨域资源共享): 通过服务器设置响应头来允许跨域请求。CORS是一种标准,允许浏览器在请求头中携带特定的信息,服务器通过响应头表示是否允许跨域请求。这是一种比较现代且安全的解决方案。
4.Nginx代理跨域: 使用Nginx等服务器作为中间层,将跨域请求先发送到Nginx服务器,然后由Nginx服务器再去请求目标服务器,最后再将结果返回给客户端。这样也可以绕过浏览器的同源策略。

这些方法各有优劣,具体的选择取决于实际需求和场景。

0.1+0.2 等不等于 0.3?自己封装一个让他们相等的方法

在JavaScript中,由于使用的是二进制浮点数表示法,0.10.2 无法被精确表示。这导致它们相加的结果在二进制表示中存在舍入误差,使得最终结果变成一个接近但不完全等于 0.3 的数字,例如 0.30000000000000004。
为了解决这个问题,有两种常见的方法:
方法1:设置误差范围值
在JavaScript中,可以使用机器精度,通常表示为 2 的负 52 次方(2^-52),即 Number.EPSILON。通过比较两个浮点数之差的绝对值是否小于 Number.EPSILON,可以判断它们是否在可接受的误差范围内相等。
function numbersEqual(a, b) {
    return Math.abs(a - b) &lt; Number.EPSILON;
}

这个函数可以用于比较两个浮点数是否相等,考虑到了可能的舍入误差。
方法2:转为整数运算
另一种方法是将浮点数转换为整数进行运算,然后再将结果转回浮点数。这是因为整数在二进制表示中不会有舍入误差。
function numbersEqual(a, b) {
    // 将浮点数转换为整数,乘以一个足够大的值
    const intA = a * 1e15;
    const intB = b * 1e15;

    // 判断整数是否相等
    return intA === intB;
}

这个方法通过乘以一个足够大的值,将小数点移动到整数位,避免了浮点数的舍入误差。
这两种方法都可以用来处理在JavaScript中由于浮点数表示不精确而导致的数学运算误差。

2018/01/01 转换成 2018年/1月/1日

function fun(str){
    var date = new Date(str)
    return date.getFullYear()+'年/'+date.getMonth()+'月/'+date.getDate()+'日'
}

ES6 的新特性

1. constlet
2. 模板字符串
3. 解构赋值
4. 对象简写法
5. for...of循环
6. 展开运算符
7. 剩余参数(可变参数)
8. ES6箭头函数
9. 参数默认值
10.类和继承
11.模块化规范

map 和 foreach 的区别

forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。
map()方法会得到一个新的数组并返回。

模板引擎原理

1.模板定义: 开发者创建模板,其中包含占位符表示待填充的数据,同时使用特定语法来控制模板的结构和逻辑。
2.模板解析: 模板引擎对模板进行解析,转换为内部数据结构或语法树。在这个过程中,引擎识别和记录模板中的各种标记、占位符和控制语句,以便后续处理。
3.数据插入: 应用程序准备好数据后,模板引擎将数据插入到模板中的对应位置。这可能涉及将数据与模板中的占位符匹配,或者执行特定语法来嵌入动态内容。
4.渲染生成: 根据解析后的模板和插入的数据,模板引擎生成最终输出。这输出可以是HTMLXML、纯文本等格式,具体取决于模板引擎的设计和使用场景。

jQuery 怎么找到事件源元素

$(".btn").click(function(e){
    // e 就是事件对象
    e.target; // 事件的目标 dom
    e.currentTarget; // 事件处理程序正在处理事件的那个元素
    e.srcElement; // 事件的目标 ie
});

AMD 怎么加载文件的?

引入RequireJS库: 首先,在HTML文件中引入RequireJS库,可以通过在
                    
                    

你可能感兴趣的:(javascript,前端,开发语言)