这是我参与更文挑战的第27天,活动详情查看: 更文挑战javascript
14万字 | 400 多道 JavaScript 面试题 🎓 有答案 🌠(第一部分 1-100题)html
14万字 | 400 多道 JavaScript 面试题 🎓 有答案 🌠(第二部分 101-200题)java
14万字 | 400 多道 JavaScript 面试题 🎓 有答案 🌠(第三部分 201-300题)node
14万字 | 400 多道 JavaScript 面试题 🎓 有答案 🌠(第四部分 301-370题)react
14万字 | 400 多道 JavaScript 面试题 🎓 有答案 🌠(第五部分 371-424题)web
为了方便手机阅览,我在必要位置都放了回顶部或者回对应问题的连接面试
有不少方法能够在 javascript 中建立对象,以下所示正则表达式
建立空对象的最简单方法是使用 Object 构造函数。目前不推荐这种方法。typescript
var object = new Object();
复制代码
Object 的 create 方法经过将原型对象做为参数传递来建立一个新对象shell
var object = Object.create(null);
复制代码
当传递 null 做为参数时,对象字面量语法等效于 create 方法
var object = {};
复制代码
建立任何函数并应用 new 运算符来建立对象实例,
function Person(name){
var object = {};
object.name=name;
object.age=21;
return object;
}
var object = new Person("Sudheer");
复制代码
这相似于函数构造函数,但它使用原型做为其属性和方法,
function Person(){}
Person.prototype.name = "Sudheer";
var object = new Person();
复制代码
这等效于使用具备函数原型的对象建立方法建立的实例,而后使用实例和参数做为参数调用该函数。
function func {};
new func(x, y, z);
复制代码
(或者)
// 使用函数原型建立一个新实例。
var newInstance = Object.create(func.prototype)
// 调用函数
var result = func.call(newInstance, x, y, z),
// 若是结果是非空对象,则使用它,不然只使用新实例。
console.log(result && typeof result === 'object' ? result : newInstance);
复制代码
ES6 引入类特性来建立对象
class Person {
constructor(name) {
this.name = name;
}
}
var object = new Person("Sudheer");
复制代码
Singleton 是一个只能实例化一次的对象。对其构造函数的重复调用返回相同的实例,这样能够确保它们不会意外建立多个实例。
var object = new function(){
this.name = "Sudheer";
}
复制代码
原型链用于基于现有对象构建新类型的对象。它相似于基于类的语言中的继承。
对象实例上的原型可经过Object.getPrototypeOf(object)
或proto
属性得到,而构造函数上的原型可经过Object.prototype
得到。
Call、Apply 和 Bind 之间的区别能够用下面的例子来解释,
call: call() 方法调用一个函数,给定的this值和参数一一提供
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.call(employee1, 'Hello', 'How are you?'); // Hello Haiyong Rodson, How are you?
invite.call(employee2, 'Hello', 'How are you?'); // Hello Jimmy Baily, How are you?
复制代码
apply:调用具备给定this值的函数,并容许你将参数做为数组传入
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.apply(employee1, ['Hello', 'How are you?']); // Hello Haiyong Rodson, How are you?
invite.apply(employee2, ['Hello', 'How are you?']); // Hello Jimmy Baily, How are you?
复制代码
bind:返回一个新函数,容许你传递任意数量的参数
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
var inviteEmployee1 = invite.bind(employee1);
var inviteEmployee2 = invite.bind(employee2);
inviteEmployee1('Hello', 'How are you?'); // Hello Haiyong Rodson, How are you?
inviteEmployee2('Hello', 'How are you?'); // Hello Jimmy Baily, How are you?
复制代码
Call 和 apply 能够互换。二者都当即执行当前函数。你须要决定是发送数组仍是逗号分隔的参数列表更容易。你能够经过处理 Call 用于逗号(分隔列表)和 Apply 用于Array来记住。
而 Bind 建立一个新函数,该函数将this设置为传递给 bind() 的第一个参数。
JSON是一种基于文本的数据格式,遵循 JavaScript 对象语法,由道格拉斯·克罗克福德 (Douglas Crockford) 推行。 当你想经过网络传输数据时它颇有用,它基本上只是一个扩展名为 .json 的文本文件,以及一个 MIME 类型的 application/json
解析:将字符串转换为原生对象
JSON.parse(text)
复制代码
字符串化:将本机对象转换为字符串,以即可以经过网络传输
JSON.stringify(object)
复制代码
所述slice()
方法返回在数组做为新的数组对象中选定的元件。它选择从给定开始参数开始的元素,并在给定的可选结束参数处结束,不包括最后一个元素。若是省略第二个参数,则它会一直选择到最后。
这种方法的一些例子是,
let arrayIntegers = [1, 2, 3, 4, 5];
let arrayIntegers1 = arrayIntegers.slice(0,2); // returns [1,2]
let arrayIntegers2 = arrayIntegers.slice(2,3); // returns [3]
let arrayIntegers3 = arrayIntegers.slice(4); //returns [5]
复制代码
==注意==: Slice 方法不会改变原始数组,而是将子集做为新数组返回。
splice() 方法用于向/从数组添加/删除项目,而后返回被删除的项目。第一个参数指定插入或删除的数组位置,而选项第二个参数指示要删除的元素数。每一个附加参数都添加到数组中。
这种方法的一些例子是,
let arrayIntegersOriginal1 = [1, 2, 3, 4, 5];
let arrayIntegersOriginal2 = [1, 2, 3, 4, 5];
let arrayIntegersOriginal3 = [1, 2, 3, 4, 5];
let arrayIntegers1 = arrayIntegersOriginal1.splice(0,2); // returns [1, 2]; original array: [3, 4, 5]
let arrayIntegers2 = arrayIntegersOriginal2.splice(3); // returns [4, 5]; original array: [1, 2, 3]
let arrayIntegers3 = arrayIntegersOriginal3.splice(3, 1, "a", "b", "c"); //returns [4]; original array: [1, 2, 3, "a", "b", "c", 5]
复制代码
==注意==: Splice 方法修改原始数组并返回删除的数组。
表格形式的一些主要区别
slice() | splice() |
---|---|
不修改原始数组(不可变) | 修改原始数组(可变) |
返回原始数组的子集 | 将删除的元素做为数组返回 |
用于从数组中选取元素 | 用于在数组中插入或删除元素 |
Object 与Maps 的类似之处在于,它们都容许您将键设置为值、检索这些值、删除键以及检测某个键是否存储了某些内容。因为这个缘由,对象在历史上被用做地图。可是在某些状况下,使用 Map 有一些重要的区别。
map =Object.create(null)
绕过,但不多这样作。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
[]==[] or []===[] //false, refer different objects in memory
{}=={} or {}==={} //false, refer different objects in memory
复制代码
箭头函数是函数表达式的较短语法,没有本身的this、arguments、super 或 new.target。这些函数最适合非方法函数,它们不能用做构造函数。
在 Javascript 中,函数是第一类对象。头等函数意味着该语言中的函数被视为任何其余变量。
例如,在这种语言中,一个函数能够做为参数传递给其余函数,能够由另外一个函数返回,也能够做为一个值分配给一个变量。例如,在下面的示例中,分配给侦听器的处理函数
const handler = () => console.log ('This is a click handler function');
document.addEventListener ('click', handler);
复制代码
一阶函数是不接受另外一个函数做为参数而且不返回函数做为其返回值的函数。
const firstOrder = () => console.log ('I am a first order function!');
复制代码
高阶函数是接受另外一个函数做为参数或返回一个函数做为返回值或二者兼而有之的函数。
const firstOrderFunc = () => console.log ('Hello, I am a First order function');
const higherOrder = ReturnFirstOrderFunc => ReturnFirstOrderFunc();
higherOrder(firstOrderFunc);
复制代码
一元函数(即 monadic)是一个只接受一个参数的函数。它表明一个函数接受的单个参数。
让咱们以一元函数为例,
const unaryFunction = a => console.log (a + 10); // 给给定的参数加 10
复制代码
柯里化是将具备多个参数的函数转换为每一个只有一个参数的函数序列的过程。Currying 以数学家Haskell Curry 的名字命名。经过应用柯里化,n 元函数将其变成一元函数。
让咱们举一个 n-ary 函数的例子,以及它如何变成一个柯里化函数,
const multiArgFunction = (a, b, c) => a + b + c;
console.log(multiArgFunction(1,2,3));// 6
const curryUnaryFunction = a => b => c => a + b + c;
curryUnaryFunction (1); // return a function: b => c => 1 + b + c
curryUnaryFunction (1) (2); // return a function: c => 3 + c
curryUnaryFunction (1) (2) (3); // return 数字 6
复制代码
Curried 函数对于提升代码复用性和函数组合很是有用。
一个纯函数是在返回值是由它的参数没有任何反作用只有肯定的函数。即若是您在应用程序中调用具备相同参数 'n' 次和 'n' 个位置的函数,则它将始终返回相同的值。
咱们举个例子来看看纯函数和非纯函数的区别,
//不纯
let numberArray = [];
const impureAddNumber = number => numberArray.push(number);
//纯
const pureAddNumber = number => argNumberArray =>
argNumberArray.concat([number]);
//显示结果
console.log (impureAddNumber(6)); // returns 1
console.log (numberArray); // returns [6]
console.log (pureAddNumber(7) (numberArray)); // returns [6, 7]
console.log (numberArray); // returns [6]
复制代码
根据上面的代码片断,经过改变数组并返回一个与参数值无关的推送数字索引,推送函数自己是不纯的。而另外一方面,Concat获取数组并将其与另外一个数组链接起来,产生一个没有反作用的全新数组。此外,返回值是前一个数组的串联。
请记住,纯函数很重要,由于它们简化了单元测试,没有任何反作用,也不须要依赖注入。它们还避免了紧密耦合,并经过没有任何反作用使您的应用程序更难中断。这些原则经过优先使用const 而不是let与 ES6 的不变性概念结合在一块儿。
let语句声明了一个块做用域局部变量。所以,使用 let 关键字定义的变量的范围仅限于使用它的块、语句或表达式。而使用var关键字声明的变量用于定义全局变量或局部变量,而无论块做用域如何。
咱们举个例子来演示一下用法,
let counter = 30;
if (counter === 30) {
let counter = 31;
console.log(counter); // 31
}
console.log(counter); // 30 (由于这里不存在 if 块中的变量)
复制代码
以表格格式列出差别
var | let |
---|---|
它从 JavaScript 开始就可用 | 做为 ES6 的一部分引入 |
它有函数做用域 | 它有块做用域 |
变量将被提高 | 已提高但未初始化 |
让咱们举个例子看看区别, |
function userDetails(username) {
if(username) {
console.log(salary); // 因为变量提高未定义
console.log(age); // 参考错误:初始化前没法访问"age"
let age = 30;
var salary = 10000;
}
console.log(salary); //10000 (可访问到适当的函数范围)
console.log(age); //error:age未定义(因为块做用域)
}
userDetails('Haiyong');
复制代码
let
是一种数学语句,被早期的编程语言如Scheme和Basic 所采用。它是从数十种其余语言中借用而来的,这些语言let已经尽量地做为传统关键字使用var。
若是您尝试在 a 中从新声明变量,switch block则会致使错误,由于只有一个块。例如,下面的代码块抛出以下语法错误,
let counter = 1;
switch(x) {
case 0:
let name;
break;
case 1:
let name; // 从新声明的语法错误。
break;
}
复制代码
为避免此错误,您能够在 case 子句中建立一个嵌套块并建立一个新的块范围词法环境。
let counter = 1;
switch(x) {
case 0: {
let name;
break;
}
case 1: {
let name; // 没有用于从新声明的 SyntaxError。
break;
}
}
复制代码
暂时性死区是 JavaScript 中的一种行为,在使用 let 和 const 关键字声明变量时发生,但不使用 var 声明变量。在 ECMAScript 6 中,在其声明以前(在其范围内)访问letorconst变量会致使 ReferenceError。发生这种状况的时间跨度,即变量绑定的建立和声明之间,称为时间死区。
让咱们用一个例子来看看这个行为,
function somemethod() {
console.log(counter1); // undefined
console.log(counter2); // ReferenceError
var counter1 = 1;
let counter2 = 2;
}
复制代码
IIFE(当即调用函数表达式)是一个 JavaScript 函数,它在定义后当即运行。它的签名以下,
(function () {
// 在这里写逻辑
}
)
();
复制代码
使用 IIFE 的主要缘由是为了得到数据隐私,由于在 IIFE 中声明的任何变量都不能被外界访问。即,若是您尝试使用 IIFE 访问变量,则会引起以下错误,
(function () {
var message = "IIFE";
console.log(message);
}
)
();
console.log(message); //Error: message is not defined(消息未定义)
复制代码
使用模块有利于扩展有不少好处。其中一些好处是,
Memoization 是一种编程技术,它试图经过缓存先前计算的结果来提升函数的性能。每次调用 memoized 函数时,都会使用其参数来索引缓存。若是数据存在,则能够返回它,而无需执行整个函数。不然执行该函数,而后将结果添加到缓存中。
让咱们举一个添加记忆化功能的例子,
const memoizAddition = () => {
let cache = {};
return (value) => {
if (value in cache) {
console.log('Fetching from cache');
return cache[value]; // 在这里, cache.value 不能用做以数字开头的属性名称,该数字不是有效的 JavaScript 标识符。 所以,只能使用方括号表示法访问。
}
else {
console.log('Calculating result');
let result = value + 20;
cache[value] = result;
return result;
}
}
}
// memoizAddition 返回的函数
const addition = memoizAddition();
console.log(addition(20)); //输出: 40 calculated
console.log(addition(20)); //输出: 40 cached
复制代码
Hoisting是一种 JavaScript 机制,其中变量和函数声明在代码执行以前被移动到其做用域的顶部。请记住,JavaScript 只提高声明,而不是初始化。 咱们举一个简单的变量提高的例子,
console.log(message); //输出: undefined
var message = 'The variable Has been hoisted';
复制代码
上面的代码看起来像下面的解释器,
var message;
console.log(message);
message = 'The variable Has been hoisted';
复制代码
在 ES6 中,Javascript 类主要是对 JavaScript 现有的基于原型的继承的语法糖。
例如,在函数表达式中编写的基于原型的继承以下,
function Bike(model,color) {
this.model = model;
this.color = color;
}
Bike.prototype.getDetails = function() {
return this.model + ' bike has' + this.color + ' color';
};
复制代码
而 ES6 类能够定义为替代
class Bike{
constructor(color, model) {
this.color= color;
this.model= model;
}
getDetails() {
return this.model + ' bike has' + this.color + ' color';
}
}
复制代码
闭包是函数和声明该函数的词法环境的组合。即,它是一个内部函数,能够访问外部或封闭函数的变量。闭包有三个做用域链
让咱们举一个闭包概念的例子,
function Welcome(name){
var greetingInfo = function(message){
console.log(message+' '+name);
}
return greetingInfo;
}
var myFunction = Welcome('Haiyong');
myFunction('Welcome '); //输出: Welcome Haiyong
myFunction('Hello Mr.'); //输出: Hello Mr.Haiyong
复制代码
根据上面的代码,即便在外部函数返回以后,内部函数(即,greetingInfo)也能够访问外部函数做用域(即 Welcome)中的变量。
模块是指独立、可重用代码的小单元,也是许多 JavaScript 设计模式的基础。大多数 JavaScript 模块导出对象字面量、函数或构造函数
如下是在 javascript 生态系统中使用模块的好处
做用域是在运行时代码的某些特定部分中变量、函数和对象的可访问性。换句话说,范围决定了代码区域中变量和其余资源的可见性。
Service Worker 基本上是一个在后台运行的脚本(JavaScript 文件),与网页分离并提供不须要网页或用户交互的功能。Service Worker 的一些主要功能是丰富的离线体验(离线第一个 Web 应用程序开发)、按期后台同步、推送通知、拦截和处理网络请求以及以编程方式管理响应缓存。
Service Worker 不能直接访问 DOM。可是它能够经过响应经过postMessage
接口发送的消息与它控制的页面进行通讯,而且这些页面能够操做 DOM。
Service Worker 的问题在于它在不使用时会被终止,并在下次须要时从新启动,所以您不能依赖 Service Worker onfetch
和onmessage
处理程序中的全局状态。在这种状况下,服务工做者将有权访问 IndexedDB API,以便在从新启动时保持和重用。
IndexedDB 是用于客户端存储大量结构化数据(包括文件/blob)的低级 API。此 API 使用索引来启用此数据的高性能搜索。
Web 存储是一种 API,它提供了一种机制,浏览器能够经过该机制以比使用 cookie 更直观的方式在用户浏览器中本地存储键/值对。Web 存储提供了两种在客户端存储数据的机制。
post message是一种启用 Window 对象之间的跨源通讯的方法。(即,在页面和它产生的弹出窗口之间,或在页面和嵌入其中的 iframe 之间)。一般,当且仅当页面遵循同源策略(即页面共享相同的协议、端口号和主机)时,容许不一样页面上的脚本相互访问。
你能够在这篇文章中更详细地了解Cookie :
haiyong.blog.csdn.net/article/det…
cookie 是存储在您的计算机上以供浏览器访问的一段数据。Cookie 保存为键/值对。
例如,您能够建立一个名为 username 的 cookie,以下所示,
document.cookie = "username=Haiyong";
复制代码
Cookie 用于记住有关用户我的资料的信息(例如用户名)。它基本上包括两个步骤,
如下选项可用于 cookie,
默认状况下,cookie 会在浏览器关闭时被删除,但您能够经过设置到期日期(UTC 时间)来更改此行为。
document.cookie = "username=Haiyong; expires=Sat, 8 Jun 2019 12:00:00 UTC";
复制代码
默认状况下,cookie 属于当前页面。可是您可使用路径参数告诉浏览器 cookie 所属的路径。
document.cookie = "username=Haiyong; path=/services";
复制代码
document.cookie = "username=; expires=Fri, 07 Jun 2019 00:00:00 UTC; path=/;";
复制代码
注意:您应该定义 cookie 路径选项以确保您删除正确的 cookie。除非您指定路径参数,不然某些浏览器不容许删除 cookie。
如下是 cookie、本地存储和会话存储之间的一些区别,
特征 | cookie | 本地存储 | 会话存储 |
---|---|---|---|
在客户端或服务器端访问 | 服务器端和客户端 | 仅客户端 | 仅客户端 |
Lifetime | 使用 Expires 选项配置 | 直到删除 | 直到选项卡关闭 |
SSL | 支持 | 支持的 | 不支持 |
最大数据大小 | 4KB | 5 MB | 5MB |
⬆ 返回顶部 |
LocalStorage 与 SessionStorage 相同,但即便浏览器关闭并从新打开(即它没有过时时间),它也会保留数据,而在 sessionStorage 中,当页面会话结束时,数据会被清除。
Window 对象实现了WindowLocalStorage
和WindowSessionStorage
对象,它们分别具备localStorage
(window.localStorage) 和sessionStorage
(window.sessionStorage) 属性。这些属性建立 Storage 对象的实例,经过该实例能够为特定域和存储类型(会话或本地)设置、检索和删除数据项。 例如,您能够读写本地存储对象,以下所示
localStorage.setItem('logo', document.getElementById('logo').value);
localStorage.getItem('logo');
复制代码
会话存储提供了读取、写入和清除会话数据的方法
// 将数据保存到 sessionStorage
sessionStorage.setItem('key', 'value');
// 从 sessionStorage 获取保存的数据
let data = sessionStorage.getItem('key');
// 从 sessionStorage 中删除保存的数据
sessionStorage.removeItem('key');
// 从 sessionStorage 中删除全部保存的数据
sessionStorage.clear();
复制代码
StorageEvent 是在另外一个文档的上下文中更改存储区域时触发的事件。而 onstorage 属性是一个用于处理存储事件的 EventHandler。 语法以下
window.onstorage = functionRef;
复制代码
让咱们以记录存储键及其值的 onstorage 事件处理程序的示例用法为例
window.onstorage = function(e) {
console.log('The ' + e.key +
' key has been changed from ' + e.oldValue +
' to ' + e.newValue + '.');
};
复制代码
Web存储更安全,能够在本地存储大量数据,不影响网站性能。此外,信息永远不会传输到服务器。所以,这是比 Cookie 更推荐的方法。
在使用网络存储以前,您须要检查浏览器对 localStorage 和 sessionStorage 的支持,
if (typeof(Storage) !== "undefined") {
// localStorage/sessionStorage 的代码。
} else {
// 对不起! 没有网络存储支持..
}
复制代码
在使用以前,您须要检查浏览器对 Web Worker 的支持
if (typeof(Worker) !== "undefined") {
// Web worker支持的代码。
} else {
// 对不起! 没有 Web Worker 支持.
}
复制代码
您须要按照如下步骤开始使用网络工做者进行计数示例
建立 Web Worker 文件:您须要编写一个脚原本增长计数值。咱们将其命名为 counter.js
let i = 0;
function timedCount() {
i = i + 1;
postMessage(i);
setTimeout("timedCount()",500);
}
timedCount();
复制代码
这里使用 postMessage() 方法将消息回传到 HTML 页面
建立 Web Worker 对象:您能够经过检查浏览器支持来建立 Web Worker 对象。让咱们将此文件命名为 web_worker_example.js
if (typeof(w) == "undefined") {
w = new Worker("counter.js");
}
复制代码
咱们能够接收来自网络工做者的消息
w.onmessage = function(event){
document.getElementById("message").innerHTML = event.data;
};
复制代码
终止 Web Worker:Web Worker 将继续侦听消息(即便在外部脚本完成后),直到它被终止。您可使用 terminate() 方法终止对消息的侦听。
w.terminate();
复制代码
重用 Web Worker:若是将 worker 变量设置为 undefined,则能够重用代码
w = undefined;
复制代码
WebWorker 无权访问如下 javascript 对象,由于它们是在外部文件中定义的
promise是一个对象,它可能会在将来的某个时间产生一个单一的值,其中有一个已解决的值或一个未解决的缘由(例如,网络错误)。它将处于 3 种可能状态之一:已完成、已拒绝或未决。
Promise 建立的语法以下所示,
const promise = new Promise(function(resolve, reject) {
// promise description
})
复制代码
承诺的用法以下,
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("I'm a Promise!");
}, 5000);
}, reject => {
});
promise.then(value => console.log(value));
复制代码
Promise 用于处理异步操做。它们经过减小回调地狱和编写更干净的代码为回调提供了一种替代方法。
Promise 具备三种状态:
回调函数是做为参数传递给另外一个函数的函数。这个函数在外部函数内部调用以完成一个动做。
咱们举一个简单的例子来讲明如何使用回调函数
function callbackFunction(name) {
console.log('Hello ' + name);
}
function outerFunction(callback) {
let name = prompt('Please enter your name.');
callback(name);
}
outerFunction(callbackFunction);
复制代码
回调是必需的,由于 javascript 是一种事件驱动的语言。这意味着 javascript 将在侦听其余事件的同时继续执行,而不是等待响应。 让咱们举一个例子,第一个函数调用 API 调用(由 setTimeout 模拟)和下一个函数记录消息。
function firstFunction(){
// 模拟代码延迟
setTimeout( function(){
console.log('First function called');
}, 1000 );
}
function secondFunction(){
console.log('Second function called');
}
firstFunction();
secondFunction();
Output
// Second function called
// First function called
复制代码
从输出中能够看出,javascript 没有等待第一个函数的响应,而且执行了剩余的代码块。所以,回调用于确保某些代码在其余代码完成执行以前不会执行。
回调地狱是一种具备多个嵌套回调的反模式,这使得在处理异步逻辑时代码难以阅读和调试。回调地狱看起来像下面,
async1(function(){
async2(function(){
async3(function(){
async4(function(){
....
});
});
});
});
复制代码
服务器发送事件 (SSE) 是一种服务器推送技术,使浏览器可以经过 HTTP 链接从服务器接收自动更新,而无需求助于轮询。这些是一种单向通讯通道 - 事件仅从服务器流向客户端。这已用于CSDN博客更新、股票价格更新、新闻提要等。
EventSource 对象用于接收服务器发送的事件通知。例如,您能够从服务器接收消息,以下所示,
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("sse_generator.js");
source.onmessage = function(event) {
document.getElementById("output").innerHTML += event.data + "<br>";
};
}
复制代码
您能够在使用以前对服务器发送的事件执行浏览器支持,以下所示,
if(typeof(EventSource) !== "undefined") {
// 支持服务器发送的事件。 让咱们在这里有一些代码!
} else {
// 不支持服务器发送的事件
}
复制代码
如下是可用于服务器发送事件的事件列表
活动 | 说明 |
---|---|
打开 | 它在打开与服务器的链接时使用 |
留言 | 收到消息时使用此事件 |
错误 | 发生错误时发生 |
promise必须遵循一组特定的规则,
您能够将一个回调嵌套在另外一个回调中,以依次执行操做。这被称为回调中的回调。
loadScript('/script1.js', function(script) {
console.log('first script is loaded');
loadScript('/script2.js', function(script) {
console.log('second script is loaded');
loadScript('/script3.js', function(script) {
console.log('third script is loaded');
// 加载全部脚本后
});
})
});
复制代码
使用 Promise 一个接一个地执行一系列异步任务的过程称为 Promise chaining。让咱们举一个计算最终结果的promise chaining的例子,
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
console.log(result); // 1
return result * 2;
}).then(function(result) {
console.log(result); // 2
return result * 3;
}).then(function(result) {
console.log(result); // 6
return result * 4;
});
复制代码
在上述处理程序中,结果经过如下工做流程传递给 .then() 处理程序链,
1.最初的promise 在 1 秒内解决, 2.在.then经过记录 result(1) 调用该处理程序以后,而后返回一个值为 result * 2 的承诺。 3.以后,.then经过记录 result(2)将值传递给下一个处理程序,并返回一个结果为 * 3 的承诺。 4.最后.then经过记录 result(6)传递给最后一个处理程序的值并返回一个结果为 * 4 的承诺。
Promise.all 是一个将一系列承诺做为输入(可迭代)的承诺,当全部承诺都获得解决或其中任何一个被拒绝时,它就会获得解决。例如,promise.all 方法的语法以下,
Promise.all([Promise1, Promise2, Promise3]) .then(result) => { console.log(result) }) .catch(error => console.log(`Error in promises ${error}`))
复制代码
==注意==:请记住,承诺的顺序(输出结果)按照输入顺序进行维护。
Promise.race() 方法将返回首先解决或拒绝的承诺实例。让咱们举一个race()方法的例子,其中promise2首先被解析
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value); // "two" // 两个 promise 都会解决,但 promise2 更快
});
复制代码
严格模式是 ECMAScript 5 中的一项新功能,它容许您将程序或函数置于“严格”操做上下文中。经过这种方式,它能够防止执行某些操做并引起更多异常。文字表达式"use strict
";指示浏览器在严格模式下使用 javascript 代码。
经过将“错误语法”通知为实际错误,严格模式对于编写“安全”JavaScript 颇有用。例如,它消除了经过抛出错误而意外建立全局变量的状况,而且还会在分配给不可写属性、getter-only 属性、不存在的属性、不存在的变量或不存在的变量时引起错误。现有的对象。
严格模式是经过添加“use strict”来声明的;到脚本或函数的开头。 若是在脚本的开头声明,则它具备全局做用域。
"use strict";
x = 3.14; // 这将致使错误,由于 x 未声明
复制代码
若是你在函数内部声明,它具备局部做用域
x = 3.14; // 这不会致使错误。
myFunction();
function myFunction() {
"use strict";
y = 3.14; // This will cause an error
}
复制代码
双感叹号或否认 (!!) 确保结果类型是布尔值。若是它是假的(例如 0、空、未定义等),它将是假的,不然为真。
例如,您可使用如下表达式测试 IE 版本,
let isIE8 = false;
isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);
console.log(isIE8); // returns true or false
复制代码
若是您不使用此表达式,则它返回原始值。
console.log(navigator.userAgent.match(/MSIE 8.0/)); // 返回一个数组或 null
复制代码
delete 关键字用于删除属性及其值。
var user= {name: "Haiyong", age:20};
delete user.age;
console.log(user); // {name: "Haiyong"}
复制代码
您可使用 JavaScript typeof 运算符来查找 JavaScript 变量的类型。它返回变量或表达式的类型。
typeof "Haiyong Abraham" // Returns "string"
typeof (1 + 2) // Returns "number"
复制代码
undefined 属性表示一个变量没有被赋值,或者根本没有声明。未定义值的类型也是未定义的。
var user; // 值未定义,类型未定义
console.log(typeof(user)) //未定义
复制代码
任何变量均可以经过将值设置为 undefined 来清空。
user = undefined
复制代码
值 null 表示有意缺乏任何对象值。它是 JavaScript 的原始值之一。空值的类型是对象。 您能够经过将值设置为 null 来清空变量。
var user = null;
console.log(typeof(user)) //object
复制代码
如下是 null 和 undefined 之间的主要区别,
null | undefined |
---|---|
它是一个赋值值,表示变量不指向任何对象。 | 它不是已声明变量但还没有赋值的赋值值。 |
null 的类型是object | undefined 的类型是 undefined |
空值是一个原始值,表示空、空或不存在的引用。 | 未定义值是在变量还没有赋值时使用的原始值。 |
表示变量没有值 | 表示没有变量自己 |
执行原始操做时转换为零 (0) | 执行原始操做时转换为 NaN |
eval() 函数计算表示为字符串的 JavaScript 代码。字符串能够是 JavaScript 表达式、变量、语句或语句序列。
console.log(eval('1 + 2')); // 3
复制代码
如下是Window和Document之间的主要区别,
Window | Document |
---|---|
它是任何网页中的根级元素 | 它是 window 对象的直接子级。这也称为文档对象模型(DOM) |
默认状况下,窗口对象在页面中隐式可用 | 您能够经过 window.document 或 document 访问它。 |
它有alert()、confirm()等方法和文档、位置等属性 | 它提供了 getElementById、getElementByTagName、createElement 等方法 |
window.history 对象包含浏览器的历史记录。您可使用 back() 和 next() 方法加载历史记录中的上一个和下一个 URL。
function goBack() {
window.history.back()
}
function goForward() {
window.history.forward()
}
复制代码
==注意==:您也能够在没有窗口前缀的状况下访问历史记录。
所述mouseEvent getModifierState()
用于返回一个布尔值,指示指定的修饰键是否被激活。CapsLock、ScrollLock 和 NumLock 等修饰符在单击时激活,再次单击时停用。
让咱们以一个输入元素为例来检测 CapsLock 开/关行为,
<input type="password" onmousedown="enterInput(event)">
<p id="feedback"></p>
<script> function enterInput(e) { var flag = e.getModifierState("CapsLock"); if(flag) { document.getElementById("feedback").innerHTML = "CapsLock activated"; } else { document.getElementById("feedback").innerHTML = "CapsLock not activated"; } } </script>
复制代码
isNaN() 函数用于肯定一个值是否为非法数字(Not-a-Number)。即,若是该值等于 NaN,则此函数返回 true。不然返回false。
isNaN('Hello') //true
isNaN('100') //false
复制代码
如下是未声明和未定义变量之间的主要区别,
undeclared | undefined |
---|---|
这些变量不存在于程序中且未声明 | 这些在程序中声明但没有赋值的变量 |
若是您尝试读取未声明变量的值,则会遇到运行时错误 | 若是您尝试读取未定义变量的值,则会返回未定义值。 |
⬆ 返回顶部 | |
回到第50题 |
全局变量是那些在整个代码长度内均可用的变量,没有任何做用域。var 关键字用于声明局部变量,但若是省略它,它将成为全局变量
msg = "Hello" // var 缺失,它成为全局变量
复制代码
全局变量的问题是局部做用域和全局做用域的变量名冲突。调试和测试依赖全局变量的代码也很困难。
NaN 属性是一个全局属性,表示“非数字”值。即,它表示一个值不是一个合法的数字。在程序中不多使用 NaN,但在少数状况下能够用做返回值
Math.sqrt(-1)
parseInt("Hello")
复制代码
isFinite() 函数用于肯定一个数是不是一个有限的合法数。若是值为 +infinity、-infinity 或 NaN(非数字),则返回 false,不然返回 true。
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(100); // true
复制代码
事件流是在网页上接收事件的顺序。当您单击嵌套在各类其余元素中的元素时,在您的单击实际到达其目的地或目标元素以前,它必须首先触发其每一个父元素的单击事件,从全局窗口对象的顶部开始。
事件流有两种方式
事件冒泡是一种事件传播,其中事件首先在最内层的目标元素上触发,而后在同一嵌套层次结构中的目标元素的祖先(父级)上依次触发,直到到达最外层的 DOM 元素。
事件捕获是一种事件传播,其中事件首先被最外层元素捕获,而后在同一嵌套层次结构中的目标元素的后代(子级)上连续触发,直到它到达最内层 DOM 元素。
您可使用 JavaScript 提交表单,使用 document.form[0].submit()。使用 onsubmit 事件处理程序提交全部表单输入的信息
function submit() {
document.form[0].submit();
}
复制代码
window.navigator 对象包含有关访问者浏览器操做系统详细信息的信息。一些操做系统属性在平台属性下可用,
console.log(navigator.platform);
复制代码
DOMContentLoaded当初始 HTML 文档彻底加载并解析完毕,无需等待资产(样式表、图像和子框架)完成加载时,将触发该事件。而当整个页面加载时会触发 load 事件,包括全部依赖资源(样式表、图像)。
Native objects
是 ECMAScript 规范定义的 JavaScript 语言的一部分的对象。例如,ECMAScript 规范中定义的 String、Math、RegExp、Object、Function 等核心对象。Host objects
是浏览器或运行时环境(节点)提供的对象。例如,窗口、XmlHttpRequest、DOM节点等被视为宿主对象。User objects
是在 javascript 代码中定义的对象。例如,为配置文件信息建立的用户对象。您可使用如下工具或技术来调试 javascript
优势:
1.它避免了不可读的回调地狱 2.使用 .then() 轻松编写顺序异步代码 3.使用 Promise.all() 轻松编写并行异步代码 4.解决回调的一些常见问题(回调太晚、太早、屡次和吞下错误/异常)
缺点:
1.它编写了少许的复杂代码 2.若是不支持 ES6,你须要加载一个 polyfill
Attributes 在 HTML 标记上定义,而properties 在 DOM 上定义。例如,下面的 HTML 元素有两个attributes 类型和值,
<input type="text" value="Name:">
复制代码
您能够检索attribute 值以下,
const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Good morning
console.log(input.value); // Good morning
复制代码
将文本字段的值更改成“Good evening”后,它变得像
console.log(input.getAttribute('value')); // Good morning
console.log(input.value); // Good evening
复制代码
同源策略是一种防止 JavaScript 跨域边界发出请求的策略。源定义为 URI 方案、主机名和端口号的组合。若是启用此策略,则它会阻止一个页面上的恶意脚本使用文档对象模型 (DOM) 获取对另外一个网页上的敏感数据的访问权限。
void(0) 用于防止页面刷新。这将有助于消除不须要的反作用,由于它将返回未定义的原始值。它一般用于使用 href="JavaScript:Void(0);"
的 HTML 文档。 一个元素内。 即,当您单击连接时,浏览器会加载一个新页面或刷新同一页面。 可是使用此表达式将阻止这种行为。
例如,下面的连接在不从新加载页面的状况下通知消息
<a href="JavaScript:void(0);" onclick="alert('Well done!')">Click Me!</a>
复制代码
JavaScript 是一种解释型语言,而不是一种编译型语言。浏览器中的解释器读取 JavaScript 代码,解释每一行,而后运行它。现在,现代浏览器使用一种称为即时 (JIT) 编译的技术,该技术在 JavaScript 即将运行时将其编译为可执行的字节码。
是的,JavaScript 是一种区分大小写的语言。语言关键字、变量、函数和对象名称以及任何其余标识符必须始终使用一致的大写字母输入。
不,它们彻底是两种不一样的编程语言,彼此没有任何关系。可是它们都是面向对象的编程语言,而且像许多其余语言同样,它们的基本功能(if、else、for、switch、break、continue 等)遵循相似的语法。
具体区别能够查看我这篇文章:
haiyong.blog.csdn.net/article/det…
event是发生在 HTML 元素上的“事物”。在 HTML 页面中使用 JavaScript 时,JavaScript 能够react处理这些事件。HTML 事件的一些示例是,
让咱们描述一下按钮元素的点击事件的行为,
<!doctype html>
<html>
<head>
<script> function greeting() { alert('Hello! Good morning'); } </script>
</head>
<body>
<button type="button" onclick="greeting()">Click me</button>
</body>
</html>
复制代码
我已经写了很长一段时间的技术博客,而且主要经过CSDN发表,这是个人一篇面试题文章。但愿大家会喜欢!
若是你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。🤗最后,不要忘了❤或📑支持一下哦