100个JavaScript理论问题





朋友们,美好的一天!



以下是该存储库中前100个JavaScript基本问题的列表,其中有简短答案,并链接到Ilya Kantor的Modern JavaScript Tutorial(JSR)和MDN。我的应用程序



中提供了此列表和300多个练习题 该应用程序实现了一种用于记忆所研究问题的机制,并且还提供了离线工作。 对于任何可能的错误和印刷错误,我深表歉意。任何形式的反馈意见表示赞赏。 版本14.09。 请参见此处的续篇



















1.如何创建对象?



有几种方法可以做到这一点。其中一些是:

对象文字:



const object = {}


对象构造函数(不推荐):



const object = new Object()


Object.create()

方法使用此方法时,会将一个对象作为参数传递给它,它将成为新对象的原型。



//     -  
const object = Object.create(null)


构造

函数我们创建一个构造函数,并使用“ new”运算符创建该函数的一个实例-一个对象:



function Person (name) {
    const object = {}
    object.name = name
    object.age = 30
    return object
}
const user = new Person('')


类:



class Person {
    constructor(name) {
        this.name = name
    }
}

const user = new Person('')


JSR

MDN



2.什么是原型?



原型用于基于现有对象创建新对象。这种技术称为原型继承。对象实例的原型可通过Object.getPrototypeOf(对象)或__proto__属性([[Prototype]]内部隐藏属性)获得。







JSR

MDN



3. call(),apply()和bind()有什么区别?



这些方法之间的差异最容易通过示例进行解释。

call()方法使用指定的this值和以逗号分隔的参数来调用函数。



const employee1 = { firstName: '', lastName: '' }
const employee2 = { firstName: '', lastName: '' }

function invite (greet1, greet2) {
    console.log(\`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}\`)
}

invite.call(employee1, '', ' ?') // ,  .  ?
invite.call(employee2, '', ' ?') // ,  .  ?


apply()方法使用指定的this值和数组参数调用函数。



const employee1 = { firstName: '', lastName: '' }
const employee2 = { firstName: '', lastName: '' }

function invite (greet1, greet2) {
    console.log(\`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}\`)
}

invite.apply(employee1, ['', ' ?']) // ,  .  ?
invite.apply(employee2, ['', ' ?']) // ,  .  ?


bind()方法返回一个具有指定此值的新函数,并允许您将数组或任意数量的以逗号分隔的参数传递给该函数。



const employee1 = { firstName: '', lastName: '' }
const employee2 = { firstName: '', lastName: '' }

function invite (greet1, greet2) {
    console.log(\`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}\`)
}

const inviteEmployee1 = invite.bind(employee1)
const inviteEmployee2 = invite.bind(employee2)
inviteEmployee1('', ' ?') // ,  .  ?
inviteEmployee2('', ' ?') // ,  .  ?


因此,在将函数绑定到对象之后,call()和apply()方法将调用该函数。两者之间的区别在于传递参数的方式。使用方法的前几个字母可以轻松记住这种区别:call是逗号(逗号,c),apply是数组(array,a)。bind()方法返回绑定到指定对象的新函数。



JSR-调用/应用

JSR-绑定

MDN-调用

MDN-应用

MDN-绑定



4.什么是JSON?它有哪些方法?



JSON是基于Douglas Crockford发明的JavaScript对象语法的文本数据格式。它用于通过网络传输数据,通常具有扩展名.json和MIME类型application / json。

解析:将JSON字符串转换为对象。



JSON.parse(text)


字符串化:将对象转换为JSON字符串以通过网络传输。



JSON.stringify(object)


JSR

MDN



5. Array.slice()方法做什么?



slice()方法将选定的数组元素作为新数组返回。它返回以第一个参数中指定的索引开始,以但不包括第二个可选参数中指定的索引结尾的项目。如果第二个参数不存在,则将检索从第一个参数中指定的索引处开始的所有元素。



const arrayIntegers = [1, 2, 3, 4, 5]
const arrayIntegers1 = arrayIntegers.slice(0, 2) // [1, 2]
const arrayIntegers2 = arrayIntegers.slice(2, 3) // [3]
const arrayIntegers3 = arrayIntegers.slice(4) // [5]


请注意,此方法不会修改原始数组,而只会将其子集作为新数组返回。



JSR

MDN



6. Array.splice()方法做什么?



splice()方法用于向数组添加元素或从数组中删除元素。第一个参数指定添加或删除元素的起始位置,第二个可选参数指定要删除的元素数量。每个后续参数(第三个等)都添加到数组中:



let arrayOriginal1 = [1, 2, 3, 4, 5]
let arrayOriginal2 = [1, 2, 3, 4, 5]
let arrayOriginal3 = [1, 2, 3, 4, 5]

let array1 = arrayOriginal1.splice(0, 2) //  [1, 2];   = [3, 4, 5]
let array2 = arrayOriginal2.slice(3) //  [4, 5];   = [1, 2, 3]
let array3 = arrayOriginal3.slice(3, 1, 'a', 'b', 'c') //  [4];   = [1, 2, 3, 'a', 'b', 'c']


注意,splice()方法修改原始数组并返回提取元素的数组。



JSR

MDN



7. slice()和splice()有什么区别?



主要区别如下:

拼接
不更改原始数组 修改原始数组
返回原始数组的子数组 以数组形式返回移除的元素
用于从数组中检索元素 用于向数组中添加元素或从中删除元素的服务


JSR

MDN-切片

MDN-接头



8.对象和地图如何比较?



对象与映射相似,因为它们都允许您在值上设置键,检索值,删除键以及确定键是否存在值。因此,对象曾经被用作地图。但是,它们之间存在一些差异,因此在某些情况下更优选使用卡片。



  • 对象键只能是字符串和符号,映射键可以是任何值,包括函数和对象
  • 映射键是有序的,但对象键不是。因此,迭代时,将按添加键的顺序返回映射键
  • 您可以使用size属性获取地图的大小,并手动定义对象属性的数量
  • 映射是可迭代的实体,要遍历对象,必须首先以某种方式获取其键,然后遍历它们
  • 将对象用作地图时,请记住任何对象都有原型,因此地图自己的键可以与用户定义的键重叠。因此,应使用Object.create(空)来创建地图对象,但是现在很少使用此方法。
  • 在快速添加/删除键方面,对象在性能方面不如地图


JSR

MDN



9.“ ==”和“ ===”运算符有什么区别?



JavaScript提供了两种比较值的方式:严格(=== ,! ==)和抽象(== ,! ==)。在严格的比较中,将值按原样进行比较,并在宽松的比较中(如有必要)执行值类型的隐式转换(铸造)。严格的运算符使用以下规则比较不同类型的值:



  • 当两个字符串具有相同的字符集,相同的长度以及位于相同位置的相同字符时,它们是严格相等的
  • 如果两个数字相等,则两个数字严格相等。有两种特殊情况:



    • NaN等于零,包括NaN
    • 正零和负零彼此相等


  • 当布尔值都是对或错时,布尔值严格相等,即 对或错
  • 如果两个对象引用相同的对象(内存位置),则它们严格相等
  • null === undefined返回false,null == undefined返回true


一些例子:



0 == false // true
0 === false // false
1 == "1" // true
1 === "1" // false
null == undefined // true
null === undefined // false
'0' == false // true
'0' === false // false
[] == [] // 
[] === [] // false,      
{} == {} // 
{} === {} // false,      


JSR

MDN



10.什么是lambda或箭头函数?



箭头函数是编写函数表达式的一种简便方法。他们没有自己的参数,论元,super和new.target。这些函数可以替代没有方法但不能用作构造函数的函数。



function regularSum (x, y) {
    return x + y
}

const arrowSum = (x, y) => x + y


JSR

MDN



11.为什么将函数称为一流对象?



在JavaScript中,函数是一流的对象。这意味着函数可以像常规变量一样使用。

例如,一个函数可以作为参数传递给另一个函数,从另一个函数作为值返回,然后分配给变量。以下示例将一个函数分配给处理程序:



const handler = () => console.log(' -   ')
document.addEventListener('click', handler)


JSR

MDN



12.什么是一阶函数?



一阶函数是不将另一个函数作为参数且不将函数作为值返回的函数:



const firstOrder = () => console.log(' -   ')


JSR

MDN



13.什么是高阶函数?



高阶函数是将另一个函数作为参数,或者将另一个函数作为值返回的函数:



const firstOrderFun = () => console.log(' -   ')
const higherOrder = returnFirstOrderFun => returnFirstOrderFun()
higherOrder(firstOrderFunc)


JSR

MDN



14.什么是一元函数?



一元函数(monad函数)是仅包含一个参数的函数:



const unaryFun = a => console.log(a + 10) //  10        


JSR

MDN



15.什么是curry?



固化是将具有多个参数的功能转换为具有一个参数的多个功能的过程。该过程以数学家Haskell Curry命名。咖喱化将一个n元函数转换为几个一元函数(减少了该函数的稀疏性):



const sum = (a, b, c) => a + b + c
const currySum = a => b => c => a + b + c

currySum(1) //  : b => c => 1 + b + c
currySum(1)(2) //  : c => 3 + c
currySum(1)(2)(3) //   6


Currying用于启用代码重用(部分功能应用程序)和编写功能。



JSR



16.什么是纯函数?



纯函数是其返回值仅取决于传递的参数而没有副作用的函数。简而言之,如果您使用n个参数调用n次函数,并且该函数始终返回相同的值,那么它很干净:



//  
let numberArray = []
const impureAddNumber = number => numberArray.push(number)
// 
const pureAddNumber = number => argNumberArray => argNumberArray.concat([number])

console.log(impureAddNumber(1)) // 1
console.log(numberArray) // [1]
console.log(pureAddNumber(2)(numberArray)) // [1, 2]
console.log(numberArray) // [1]


在上面的示例中,impureAddNumber不是纯函数,因为push()方法返回数组的新长度,该长度与传递的参数无关。第二个函数是纯函数,因为concat()方法将两个数组连接在一起而没有副作用,并返回一个新数组。纯函数对于单元测试是必不可少的,不需要依赖注入。由于其元素之间的连接较弱,因此没有副作用可以提高应用程序的可靠性。ES6中引入了不变性的概念,此原则的化身之一是const而不是let。



JSR

MDN



17.“ let”关键字的用途是什么?



let关键字声明一个块作用域局部变量。这种变量的范围受使用它的块,运算符或表达式的限制。用“ var”关键字声明的变量具有定义它们的全局范围或函数范围:



let counter = 1
if (counter === 1) {
    let counter = 2
    console.log(counter) // 2
}
console.log(counter) // 1 ( counter,   ,   )


JSR

MDN



18. let和var有什么区别?



主要区别如下:

变种
自JavaScript起可用 在ES6中引入
具有全局或功能范围 有块范围
变量被提升到作用域的开头 变量也被吊起,但是没有初始化(仅吊起声明,而不赋值)


一些例子:



function userDetails(username) {
    if (username) {
        console.log(salary)
        console.log(age)
        let age = 30
        var salary = 10000
    }
    console.log(salary) // 10000 (  )
    console.log(age) // SyntaxError: "age" is not defined (  )
}


JSR

MDN-让

MDN-var



19.为什么选择“ let”作为关键字?



Let是早期方案(Scheme和Basic)等编程语言所使用的数学运算符。如今,大量的编程语言都使用let,因此该词是缩写“ var”(变量)的最接近替代词。



JSR

MDN



20.如何覆盖开关块中的变量?



如果您尝试覆盖在切换块中用“ let”关键字声明的变量,则会收到错误消息:



let counter = 1
switch(x) {
    case 0:
        let name
        break
    case 1:
        let name // SyntaxError
        break
}


要解决此问题,您需要在案例内创建一个新的块-一个新的词法作用域:



let counter = 1
switch(x) {
    case 0: {
        let name
        break
    }
    case 1: {
        let name
        break
    }
}


JSR

MDN



21.什么是临时死区?



如果您在定义变量之前(即在为它们分配当前范围内的值之前)尝试访问用关键字“ let”或“ const”(而不是“ var”)声明的变量,则将引发ReferenceError异常。 )。换句话说,死区是变量的上下文(范围)的创建与其定义之间的时间:



function someMethod () {
    console.log(counter1) // undefined
    console.log(counter2) // ReferenceError
    var counter1 = 1
    const counter2 = 2
}


MDN



22.什么是立即调用函数表达式(IIFE)?



IIFE是定义后立即调用的函数。此类函数的语法如下所示(其中一个选项,最常见):



(function () {
    // 
})()

// ,      
(() => {
    // 
})()


使用IIFE的主要原因是保持变量私有,因为IIFE内部声明的变量无法从外部环境访问:



(function () {
    var message = 'IIFE'
    console.log(message)
})()
console.log(message) // SyntaxError: "message" is not defined


JSR

MDN



23.使用模块有什么好处?



除其他外,可以提及以下内容:



  • 提高可读性并简化代码维护
  • 可重用代码
  • 保持全局命名空间整洁


JSR

MDN



24.什么是记忆或记忆?



记忆化是通过将先前获得的功能结果存储在缓存中来提高功能性能的一种方法。每次调用该函数时,传递给它的参数将成为缓存索引。如果数据在缓存中,则不重新执行该函数就将其返回。否则,将执行该函数并将结果写入高速缓存:



const memoAdd = () => {
    let cache = {}
    return value => {
        if (value in cache) {
            console.log('   ')
            return cache[value] //   , cache.value        ,     JavaScript     .    
        } else {
            console.log(' ')
            let result = value + 20
            cache[value] = result
            return result
        }
    }
}
//    memoAdd
const add = memoAdd()
console.log(add(20)) //   40
console.log(add(20)) //     40


25.什么是吊装?



提升是在执行代码之前将变量和函数表达式移至其范围的开头的过程。请记住:只悬挂变量和表达式本身,而不初始化它们(即悬挂变量声明,而不是赋值):



console.log(message) // undefined
var message = '!'


对于解释器,此代码如下所示:



var message
console.log(message)
message = '!'


JSR

MDN



26.什么是课程?



ES6中引入的类是用于原型继承(用于构造函数原型)的语法糖(包装,抽象或附加组件)。构造函数的示例:



function Bike(model, color) {
    this.model = model
    this.color = color
}

Bike.prototype.getDetails = function () {
    return ' ' + this.model + '   ' + this.color + ' .'
}


使用类的相同示例:



class Bike {
    constructor (color, model) {
        this.color = color
        this.model = model
    }

    getDetails () {
        return \` ${this.model}   ${this.color} .\`
    }
}


JSR

MDN



27.什么是封闭?



闭包是函数及其词法环境的组合。简而言之,闭包是当内部函数可以访问在外部函数中声明的变量时。闭包具有三个范围的链:



  • 自己的范围
  • 外部功能范围
  • 全球范围


const welcome = name => {
    const greet = message => {
        console.log(\`${message}, ${name}!\`)
    }
    return greet
}

const fun = welcome('')
fun('') // , !


JSR

MDN



28.什么是模块?



模块是构成许多设计模式基础的独立的,可重复使用的代码的小片段。大多数模块都导出为对象,函数或构造函数。



JSR

MDN



29.什么是范围?



范围定义了代码执行期间变量在不同位置的变量,函数和对象的可用性。换句话说,作用域是在当前代码执行上下文中变量和其他资源的可见性。



MDN



30.什么是服务人员?



服务工作者是独立于其运行的网页和用户的操作运行的脚本。实际上,服务工作者充当应用程序和浏览器之间的代理服务器。服务工作者的主要功能如下:确保应用程序脱机,定期后台同步,推送通知,拦截和处理网络请求以及以编程方式管理缓存。



MDN



31.您如何使用服务人员与文档对象模型(DOM)进行交互?



服务人员没有直接访问DOM的权限。但是,他们可以通过postMessage接口与页面进行交互,并且页面可以修改DOM。



MDN-ServiceWorker

MDN-postMessage



32.重新启动服务工作者时如何重用信息?



服务工作者的问题之一是,当他们不使用服务时,他们将停止执行,并在需要时重新启动。这样可以防止您全局添加获取和消息事件处理程序。要重用信息,必须确保服务工作者与索引数据库(IndexedDB)或本地存储(本地存储)进行交互。



MDN



33.什么是索引数据库(IndexedDB)?



IndexedDB是用于在客户端存储大量结构化数据(包括文件和Blob)的低级API。该接口使用索引来提高数据检索的速度。



JSR

MDN



34.什么是Web存储?



网络存储是一个界面,可让您在本地将数据存储为键/值对,即 在用户浏览器中,比使用cookie更方便。Web存储提供两种存储机制:



  • 本地存储(本地存储)-在无限时间内存储当前用户的数据
  • 会话存储-在整个当前会话中存储数据,即 关闭浏览器标签时,数据将丢失


JSR

MDN



35.什么是postMessage?



postMessage是在窗口对象的不同来源(例如,页面及其所生成的弹出窗口(弹出窗口)或页面和嵌入式iframe)之间进行通信的一种方式。通常,如果一个页面上的脚本遵循通用原点或单一源策略(源-协议,主机和端口),则该页面上的脚本无法访问另一页面。



MDN-postMessage



36.什么是cookie?



Cookie是一小段数据,存储在用户的计算机上,供浏览器稍后使用。Cookies存储为键/值对:



document.cookie = 'username='








JSR

MDN



37.为什么我们需要cookie?



Cookies用于保存有关用户的信息(不建议用于存储机密信息)。通常,此过程包括两个阶段:



  • 首次访问该页面时,用户个人资料会保存在Cookie中
  • 在重新访问页面时,将从Cookie中检索用户个人资料


JSR

MDN



38. Cookies的功能是什么?



默认情况下,关闭浏览器时会删除cookie,但是可以通过在UTC中设置到期时间来更改它:



document.cookie = 'username=; expires=Sat, 5 Sep 2020 12:00:00 UTC'


默认情况下,cookie属于当前页面,但是也可以通过设置路径来更改它:



document.cookie = 'username=; path=/services'


JSR

MDN



39.如何删除Cookie?



您可以通过将经过时间设置为生存期来删除Cookie。在这种情况下,您不需要定义cookie值:



document.cookie = 'username=; expires=Sat, 05 Jun 2020 00:00:00 UTC; path=/;'


请注意,在这种情况下,必须确定删除正确cookie的路径。某些浏览器不允许您在不指定此参数的情况下删除cookie。



JSR

MDN



40. Cookie,本地存储和会话存储之间有什么区别?



主要区别如下:

标准 饼干 本地存储 会话存储
可用性 在服务器和客户端上 仅客户 仅客户
一生 安装到期 直到用户删除 直到关闭浏览器选项卡
加密支持 支持的 不支持 不支持
最大数据量 4公斤 大约5 MB(取决于浏览器) 大约5 MB(取决于浏览器)


JSR-Cookie

MDN-Cookie

JSR-LocalStorage,SessionStotage

MDN-网络存储



41.本地存储和会话存储之间的主要区别是什么?



本地存储与会话存储相同,不同之处在于,第一,即使关闭并重新启动浏览器,也会保存数据;第二,在会话结束时(关闭浏览器选项卡),数据将被删除。



JSR

MDN



42.如何访问网络存储?



window对象提供分别具有localStorage和sessionStorage属性的WindowLocalStorage和WindowSessionStorage对象。这些属性创建一个Storage对象的实例,您可以使用该对象来写入,检索和删除特定域和存储类型(会话或本地)的数据:



//  
localStorage.setItem('data', document.querySelector('.data').value)
//  
localStorage.getItem('data')


JSR

MDN



43.会话存储提供什么方法​​?



会话存储提供了读取,写入和删除数据的方法:



//  
sessionStorage.setItem('key', 'value')

//  
const data = sessionStorage.getItem('key')

//   
sessionStorage.removeItem('key')

//   
sessionStorage.clear()


JSR

MDN



44.使用网络存储时发生什么事件?



当存储在另一个文档的上下文中更改时,将引发存储事件:



window.onstorage = function () {}


处理此事件的示例:



window.onstorage = event => {
    console.log(\`${event.key}  .
     : ${event.oldValue}.
     : ${event.newValue}.\`)
}


此事件使您可以实现一种聊天。



JSR

MDN



45.网络存储有什么作用?



Web存储比cookie更安全,并且可以存储更多数据,而不会影响性能。此外,数据不会发送到服务器(对于cookie,每次客户端访问服务器时,数据都包含在请求和响应标头中)。因此,这种存储数据的方式优于cookie。



JSR

MDN



46.如何确定浏览器是否支持Web存储?



在使用网络存储之前,建议检查浏览器对此接口的支持:



if (typeof(Storage) !== 'undefined') {
    // 
} else {
    // -  
}

// 
if ('Storage' in window) {
    console.log('ok')
} else {
    console.warn(' ok')
}


根据CanIUse的说法,今天的网络存储支持率为98%。



JSR

MDN



47.如何确定浏览器是否支持服务人员?



在使用服务工作者之前,建议检查浏览器对此接口的支持:



if (typeof(Worker) !== undefined) {
    // 
} else {
    // -  
}
// 
if ('Worker' in window) {
    console.log('ok')
} else {
    console.warn(' ok')
}


CanIUse称,今天的服务人员支持率为94%。



MDN



48.举一个网络工作者的例子



要使用Web Worker,您需要执行以下操作。

为工作程序创建一个文件,例如get-current-time.js:



const getCurrentTime = () => {
    let time = new Date().toLocaleTimeString()
    postMessage(time)
    setTimeout(() => getCurrentTime(), 1000)
}

getCurrentTime()


postMessage()方法用于将消息发送到页面。

创建一个工作对象:



const worker = new Worker('get-current-time.js')


之后,我们处理来自工作程序的消息接收:



<output></output>
<button></button>

worker
    .addEventListener('message', event => document.querySelector('output')
    .textContent = event.data)


即使在外部脚本完成其工作之后,该工作程序仍将继续处理该消息事件,因此必须强制停止该事件:



document.querySelector('button')
    .addEventListener('click', () => worker.terminate())


如果将worker设置为undefined,则可以重用它:



worker = undefined


MDN



49.网络工作者使用DOM的局限性是什么



由于Web工作人员是在单独的文件中创建的,因此他们无权访问以下对象:



  • 窗口
  • 文件
  • 父对象-启动工作程序的对象


MDN



50.什么是诺言?



一个promise(通讯)是一个以某个值执行或被错误拒绝的对象。在某个时间过去之后或某个事件发生之后,解决承诺。一个承诺可以具有以下三种状态之一:未决,已实现和被拒绝。

无极语法:



const promise = new Promise((resolve, reject) => {
    // 
})

// ,   ,    
const promise = Promise.resolve(value)
promise.then(value => {
    // 
})


使用诺言的示例:



const promise = new Promise(resolve => {
    const timer = setTimeout(() => {
        resolve('  !')
        clearTimeout(timer)
    }, 5000);
}, reject => {
    reject('-   ')
})

promise
    .then(value => console.log(value))
    .catch(error => console.error(error))
    .finally(() => console.log(' ')) //     "  !"  5    " "


承诺解决算法:







JSR

MDN



51.为什么需要诺言?



承诺用于处理异步代码。它们是回调函数的替代方法,避免了所谓的“回调地狱”,使代码更整洁且更具可读性。



JSR

MDN



52.列出承诺的三种可能状态



承诺具有三种状态:



  • 待定:开始操作之前的阶段
  • 已完成:操作成功完成
  • 拒绝:操作失败。抛出异常


JSR

MDN



53.什么是回调函数?



回调是一个作为参数传递给另一个函数的函数。当特定事件发生时,在父级(外部)中调用此函数(内部)以执行操作。让我们看一个简单的例子:



function callback(name) {
    alert(\`, ${name}!\`)
}

function outer(cb) {
    const name = prompt(',   ')
    cb(name)
}
outer(callback)


在上面的示例中,外部函数请求用户的名称并将其存储在name变量中。然后,此函数将名称传递给回调函数,该回调函数输出带有用户名的问候语。



JSR

MDN



54.为什么需要回调?



因为JavaScript是一种事件驱动的语言,所以需要回调。这意味着,例如,JavaScript不再等待对请求的响应或要处理的特定事件,而是继续响应其他事件。考虑一个示例,其中一个函数访问界面,另一个函数向控制台输出消息:



function first () {
    //    API
    setTimeout(() => console.log('  '), 1000)
}

function second () {
    console.log('  ')
}

first()
second()
//    "  ",  "  "


如您所见,JavaScript不会等待第一个函数完成,而是继续执行代码。因此,回调用于模拟异步,从而防止主程序线程被阻塞。



JSR

MDN



55.什么是回调地狱?



回调地狱是一种反模式,其中许多回调函数相互嵌套以实现异步逻辑。这种代码结构很难理解和维护。它可能看起来像这样:



function first () {
    return function second () {
        return function third () {
            return function fourth () {
                //  ..
            }
        }
    }
}


这种方法被认为是不好的做法,除非是有粗俗,部分应用或功能组合的情况。



JSR

MDN



56.什么是服务器发送事件(SSE)?



服务器发送事件是一种推送通知技术,它使浏览器可以通过HTTP连接从服务器接收更新的数据,而无需发送请求。当消息仅由服务器发送时,这是客户端与服务器之间进行通信的方式之一。该技术用于更新Facebook / Twitter,商店价格,新闻提要等。



JSR

MDN



57.如何接收服务器发送的消息(通知或事件)?



EventSource对象用于此目的:



if('EventSource' in window) {
    const source = new EventSource('sse.js')
    source.addEventListener('message', event => document.querySelector('output')
        .textContent = event.data)
}


JSR

MDN



58.如何检查浏览器对SSE的支持?



这样做是这样的:



if (typeof EventSource !== 'undefined') {
    // 
} else {
    // SSE  
}

// 
('EventSource' in window)
    ? console.log('ok')
    : console.warn('! ok')


CanIUse称, SSE当前支持95%的浏览器。



JSR

MDN



59.使用SSE时会发生什么事件?



以下是这些事件的列表:

事件 描述
打开 在打开与服务器的连接时发生
信息 从服务器接收消息时发生
错误 引发异常时抛出


JSR

MDN



60.履行承诺的基本规则是什么?



兑现承诺的基本规则如下:



  • promise是一个包含内置或标准then()方法的对象
  • 等待承诺的阶段通常以履行或拒绝的阶段结束
  • 已兑现或拒绝的承诺一旦解决,其状态就不应更改
  • 在兑现承诺后,其价值也不应改变。


JSR

MDN



61.什么是回调?



您可以相互嵌套回调,以便顺序执行某些操作:



loadScript('/script1.js', script => {
    console.log(\` ${script} \`)

    loadScript('/script2.js', script => {
        console.log(\` ${script} \`)

        loadScript('/script3.js', script => {
            console.log(\` ${script} \`)
        })
    })
})


JSR

MDN



62.什么是承诺链?



使用诺言顺序执行多个异步任务称为诺言链。让我们考虑一个例子:



new Promise((resolve, reject) => {
    const id = setTimeout(() => {
        resolve(1)
        clearTimeout(id)
    }, 1000)
}).then(result => {
    console.log(result) // 1
    return result * 2
}).then(result2 => {
    console.log(result2) // 2
    return result2 * 3
}).then(result3 => {
    console.log(result3) // 6
}).catch(error => console.error(error))


执行算法:



  • 第一个承诺的值为1
  • 之后,第一个then()方法将此值输出到控制台,并将其乘以2返回
  • 第二个then()将第一个then()的结果打印到控制台(2),并将结果乘以3
  • 最后一个()将第二个()的结果打印到控制台(6)
  • catch块用于处理错误


JSR

MDN



63.什么是Promise.all()?



Promise.all()是一个承诺,它将其他承诺的数组作为参数,并返回已实现承诺的结果,如果拒绝则返回错误。句法:



Promise.all([Promise1, Promise2, Promise3])
    .then(results => console.log(results))
    .catch(error => console.error(error))


请记住,触发结果的顺序取决于数组中promise的顺序。



JSR

MDN



64.什么是Promise.race()?



Promise.race()返回以承诺数组形式传递的第一个已实现或拒绝的承诺的结果:



const promise1 = new Promise((resolve, reject) => setTimeout(resolve, 500, ''))

const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, ''))

Promise.race([promise1, promise2]).then(value => console.log(value)) // ""


JSR

MDN



65.什么是严格制度?



要启用严格模式,请在所有代码或单个函数的开头使用“使用严格”(或“使用严格”)语句。ES5中引入了严格模式。在此模式下,禁止某些操作,并引发更多异常。



JSR

MDN



66.为什么需要严格的制度?



严格模式允许您通过防止发生许多错误来编写更安全的代码。例如,它不允许意外创建全局变量(无关键字,变量=值),将值分配给只读属性,只能使用getter获取的属性,不存在的属性以及不存在的变量或对象。在非严格模式下,在所有这些情况下均不会引发异常。



JSR

MDN



67.如何启用严格的安全性?



在代码或函数开头的“使用严格”(或“使用严格”)语句启用严格模式。通常,该指令在脚本的最开始处指示,即 在全局名称空间中:



'use strict'
x = 3.14 // ReferenceError: "x" is not defined


如果在函数中指定了“使用严格”,那么严格模式仅适用于该函数:



x = 3.14 //   
f() // ReferenceError: "y" is not defined

function f () {
    'use strict'
    y = 3.14
}


JSR

MDN



68.双重否定的作用是什么?



双重否定(!!)将值转换为布尔值。如果值为false,则返回false,否则-true:



const x = 1
console.log(x) // 1
console.log(!!x) // true
const y = ''
console.log(y) // ''
console.log(!!str) // false


注意:!!!不是单独的运算符,而是两个运算符!..



MDN

JSR



69. delete运算符用于什么?



该运算符用于删除对象的属性以及这些属性的值:



'use strict'
const user = {
    name: '',
    age: 30
}

delete user.age

console.log(user) // { name: "" }

delete user // SyntaxError: Delete of an unqualified identifier in strict mode


请注意,在非严格模式下,删除对象的尝试将自动失败。

由于数组也是对象,因此将delete应用于数组的元素将删除其值并向其写入未定义的值,即 数组中已删除元素的索引将保留,并且数组的长度不会更改。



JSR

MDN



70. typeof运算符用于什么?



此运算符用于定义变量或表达式的类型:



typeof 1 // number
typeof [] // object
typeof '' // string
typeof (1 + 2) // number

typeof null // object
typeof NaN // number


JSR

MDN



71.未定义的是什么?



undefined是尚未分配值的变量以及未声明变量的未定义(但不会丢失)标准值(默认值)。这是原始数据类型之一:



let name
console.log(typeof name) // undefined
console.log(typeof age) // undefined


此值可以显式分配给变量:



user = undefined


JSR

MDN



72.什么是null?



null是表示不存在的值(明确设置)的值。这是原始数据类型之一。使用null,可以删除变量的值:



const user = null
console.log(typeof user) // object


JSR

MDN



73. null和undefined有什么区别?



主要区别如下:

空值 未定义
分配为无价值指标 是尚未分配值的变量或未声明变量的默认值
类型-对象 类型-未定义
原始类型,表示空,无值或无引用 基本类型,表示未将值分配给变量
表示没有变量值 表示没有变量或变量值不确定


JSR-未定义

JSR-空

MDN-未定义

MDN-空



74.什么是评估?



eval()函数评估传递给它的字符串。字符串可以是表达式,变量,一个或多个运算符:



console.log(eval('1 + 2')) // 3

//   
const curryCalc = x => operator => y =>
    new Promise((resolve, reject) =>
        resolve(eval(\`x${operator}y\`))
    ).then(
        result => console.log(result),
        error => console.error(' !')
    )

curryCalc(1)('+')(2) // 3
curryCalc(4)('-')(3) // 1
curryCalc(5)('x')(6) //  !


不建议使用。



JSR

MDN



75.如何访问浏览器历史记录?



有关浏览器中页面之间的移动历史的信息包含窗口对象的history属性。要转到上一页或下一页,请使用back(),next()或go()方法:



const goBack = () => {
    history.back()
    // 
    history.go(-1)
}

const goForward = () => history.forward()


MDN



76. JavaScript中有哪些类型的数据?



JavaScript有8种主要类型:



  • 任何数量的数字:整数或浮点数,整数值限制为±2 53
  • bigint用于任意长度的整数
  • 字符串的字符串。字符串可以包含一个或多个字符,没有单独的字符类型
  • 布尔值true / false
  • 对于未知值为null-具有单个null值的不同类型
  • 对于未分配的值未定义-具有一个未定义值的单独类型
  • 更复杂的数据结构的对象
  • 唯一标识符的符号


JSR

MDN



77. isNaN()是做什么的?



isNaN()函数将值转换为数字并检查其是否为NaN。



isNaN('hello') // true
isNaN(100) // false


此功能的更强大版本是ES6中引入的Number.isNaN()方法。



JSR

MDN



78.未声明变量和未定义变量有什么区别?



主要区别如下:

未声明 未定义
程序中不存在 已声明但未分配值
访问尝试以错误结束 尝试访问时返回未定义
爬到当前范围的开头 也上升,但没有分配的值,即 具有未定义的值(仅悬挂声明,而不初始化)


JSR

MDN



79.什么是全局变量?



在浏览器中,用“ var”关键字声明或不使用关键字(在宽松模式下)声明的全局函数和变量将成为全局窗口对象的属性(在模块中不起作用)。可从程序中的任何位置访问此类变量。不建议使用全局变量。如果需要创建全局变量,则最好显式地进行操作:



window.currentUser = {
    name: ''
}

// 
globalThis.currentUser = {
    name: ''
}

console.log(currentUser.name) // 


JSR



80.创建全局变量会带来哪些问题?



创建全局变量会污染全局名称空间,这可能导致变量名称之间发生冲突。这也使得调试和测试代码变得更加困难。



JSR



81.什么是NaN?



全局NaN属性是一个非数字值。更准确地说,NaN表示该值不正确,但仍然是一个数字。因此typeof NaN返回数字。



parseInt('bla') // NaN
Math.sqrt(-1) // NaN


MDN



82. isFinite()有什么作用?



全局函数isFinite()将参数转换为数字,如果它是普通(有限)数字,则返回true。不是NaN,无穷大(正无穷大),-无穷大(负无穷大)。否则,返回false。



isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false

isFinite(100) // true


还有一个Number.isFinite()方法,与isFinite()不同,该方法不会在检查之前将参数转换为数字。



MDN

JSR



83.什么是事件流/传播?



事件流(事件传播)是事件在页面上发生的顺序。当您单击嵌套在其他元素中的元素时,在事件到达目标元素之前,它将从全局窗口对象开始依次遍历其所有祖先。事件传播分为三个阶段:



  • 从上到下-捕获或潜水阶段
  • 目标阶段
  • 自下而上-上升或上升的阶段(不要与增加变量相混淆-吊装)


JSR



84.什么是事件冒泡?



起泡是事件传播的阶段,当事件首先在目标元素上注册,然后从该元素的祖先到最顶层(外部)元素(全局窗口对象)的链上。



JSR



85.什么是沉浸式或事件捕获?



浸入是一个事件发生的阶段,该事件首先在最顶层(外部)元素(全局窗口对象)上注册,然后沿祖先链下降到目标元素。



JSR



86.如何提交表格进行处理?



这可以通过不同的方式完成:



function submitForm() {
    document.forms[0].submit()
}

form.onsubmit = function(event) {
    event.preventDefault()
    // 
}

form.addEventListener('submit', event => {
    event.preventDefault()
    // 
})


默认情况下,表单上的任何按钮都是提交的 用于提交表格。



JSR

MDN



87.如何获得有关操作系统的信息?



此信息包含在全局导航器对象中。某些信息可以通过其platform属性获得:



console.log(navigator.platform)


MDN



88. DOMContentLoaded事件和load事件有什么区别?



当原始HTML文档已完全加载和解析而无需等待样式表,图像或框架完全加载时,将引发DOMContentLoaded事件。页面完全加载(包括所有其他资源)后,将触发load事件。



JSR

MDN-DOMContentLoaded

MDN-负载



89.本机,主机(由代码运行时拥有)和自定义对象之间有什么区别?



本机对象是语言的一部分,并在ECMAScript规范中定义。此类对象是例如Number,String,Function,Object,Math,RegExp,Date等。主机对象由浏览器或其他运行时(例如Node.js)提供。这样的对象是例如窗口,文档(DOM),XMLHttpRequest,Web API(调用堆栈,任务队列)等。用户对象是用代码创建的任何对象,例如,对象包含有关用户的信息:



const user = {
    name: '',
    age: 30
}


JSR

MDN



90.哪些工具用于延迟代码?



这些手段是:



  • 浏览器内开发人员工具,例如Chrome DevTools
  • 调试器表达式
  • 好的旧console.log()


JSR

MDN-调试器

MDN-控制台



91. promises和callbacks有什么优点和缺点?



好处:



  • 防止回调
  • 使您可以依次使用then()执行异步代码
  • 允许异步代码使用Promise.all()并行执行
  • 解决许多回调问题(调用得太晚或太早,多次调用而不是一次,错误隐藏)


缺点



  • 代码变得更难编写
  • 为了支持较旧的浏览器,需要使用polyfill(如今几乎没有这种浏览器了)


JSR-承诺

JSR- MDN回调

-Promise

MDN-回调



92.属性和元素属性有什么区别?



当浏览器加载页面时,它将解析HTML并从中生成DOM对象。对于元素节点,大多数标准HTML属性会自动成为DOM对象的属性。那些。元素的属性在标记中指定,其属性在DOM中。例如,对于具有id =“ page”属性的body标签,DOM对象将具有body.id =“ page”属性。



<input type="text" value=" !">
//     : type  value

const input = document.querySelector('input')
//  
console.log(input.getAttribute('value'))
//  
console.log(input.value)

//   
input.setAttribute('value', ' !')
//   
input.value = ' !'


请注意,ECMAScript规范还定义了对象属性的属性-[[Value]],[[Writable]],[[Enumerable]]和[[Configurable]]。



JSR



93.什么是同源政策(SOP)?



共享源(同一源)策略阻止访问其他源的数据。源是协议,主机和端口的组合。默认情况下,跨域资源共享(CORS)是禁止的,即 仅响应来自相同数据源的请求提供数据。可以使用特殊的HTTP标头更改此行为。



JSR

MDN-SOP

MDN-CORS



94. void 0做什么?



void运算符评估传递的表达式并返回未定义的。通常,当我们单击链接时,浏览器将加载新页面或重新加载当前页面。您可以通过使用表达式“ void(0)”来避免这种情况:



<a href="javascript:void(0)" onclick="alert('!')">  !
</a>


页面重新加载也可以通过一个简单的存根来防止:



<a href="#"> </a>
//     "#"   URL   


MDN



95. JavaScript是编译的还是解释的编程语言?



JavaScript本身是一种解释型编程语言。引擎解析代码,解释每一行并执行它。但是,现代浏览器使用一种称为即时(JIT编译)的技术,该技术在执行之前先编译(优化)代码。这增加了代码执行的准备时间,但大大加快了执行速度。例如,Chrome和Node.js中使用的引擎V8使用Ignition解释器来解析代码,并使用TurboFan编译器来优化代码。



JSR

MDN



96. JavaScript是否区分大小写?



是的,JavaScript区分大小写。因此,使用关键字时,关键字,变量名称,函数和对象必须相同。例如,const somename和const someName是不同的变量,typeof(1)是数字,typeOf 1是ReferenceError:未定义typeOf。



JSR

MDN



97. Java和JavaScript相关吗?



不,它们是两种不同的编程语言。但是,它们都属于面向对象的语言,并且像许多其他语言一样,使用类似的语法(如果是,则为for切换,中断,继续等)。基本上,Java到JavaScript是一种营销策略。



JSR

MDN



98.什么是活动?



事件是浏览器对特定操作的反应。此操作可以是用户操作,例如,单击按钮或输入文本,加载页面,接收对请求的响应等。(触发事件的动作不一定是特定于用户的)。记录事件以进行进一步处理。



button.onclick = () => alert('!')

input.addEventListener('change', function() {
    p.textContent = this.value
})

window.onload = () => console.log('  ')


MDN

JSR



99.谁发明了JavaScript?



JavaScript是由Brendan Eich在Netscape Communications期间创建的该语言最初称为Mocha,然后将其重命名为LiveScript,旨在用于客户端编程和服务器端编程(在此处应称为LiveWire)。



JSR

MDN



All Articles