.我们可以在下列哪个 HTML 元素中放置 Javascript 代码?()
A.<script>
B.<javascript>
C.<js>
D.<scripting>
2.写 "Hello World" 的正确 Javascript 语法是?()
A.("Hello World")
B."Hello World"
C.response.write("Hello World")
D.document.write("Hello World")
3.插入 Javacript 的正确位置是?()
A.<body>部分
B.<head>部分
C.<body>部分和<head>部分均可
4.引用名为 "xxx.js" 的外部脚本的正确语法是?()
A.<script src="xxx.js">
B.<script href="xxx.js">
C.<script name="xxx.js">
5.如何在警告框中写入 "Hello World"?()
A.alertBox="Hello World"
B.msgBox("Hello World")
C.alert("Hello World")
D.alertBox("Hello World")
6.如何创建函数?()
A.function:myFunction()
B.function myFunction()
C.function=myFunction()
7.如何调用名为 "myFunction" 的函数?()
A.call function myFunction
B.call myFunction()
C.myFunction()
8.如何编写当 i 等于 5 时执行一些语句的条件语句?()
A.if (i==5)
B.if i=5 then
C.if i=5
D.if i==5 then
9.如何编写当 i 不等于 5 时执行一些语句的条件语句?()
A.if =! 5 then
B.if >< 5
C.if (i >< 5)
D.if (i != 5)
10.在 JavaScript 中,有多少种不同类型的循环?()
A.两种。for 循环和 while 循环。
B.四种。for 循环、while 循环、do...while 循环以及 loop...until 循环。
C.一种。for 循环。
11.for 循环如何开始?()
A.for (i <= 5; i++)
B.for (i = 0; i <= 5; i++)
C.for (i = 0; i <= 5)
D.for i = 1 to 5
12.如何在 JavaScript 中添加注释?()
A.' This is a comment
B.<!--This is a comment-->
C.//This is a comment
13.可插入多行注释的 JavaScript 语法是?()
A./*This comment has more than one line*/
B.//This comment has more than one line//
C.<!--This comment has more than one line-->
14.定义 JavaScript 数组的正确方法是?()
A.var txt = new Array="George","John","Thomas"
B.var txt = new Array(1:"George",2:"John",3:"Thomas")
C.var txt = new Array("George","John","Thomas")
D.var txt = new Array:1=("George")2=("John")3=("Thomas")
15.如何把 7.25 四舍五入为最接近的整数?()
A.round(7.25)
B.rnd(7.25)
C.Math.rnd(7.25)
D.Math.round(7.25)
16.如何求得 2 和 4 中最大的数?()
A.Math.ceil(2,4)
B.Math.max(2,4)
C.ceil(2,4)
D.top(2,4)
17.打开名为 "window2" 的新窗口的 JavaScript 语法是?()
A.open.new("http://www.w3cschool.cn","window2")
B.new.window("http://www.w3cschool.cn","window2")
C.new("http://www.w3cschool.cn","window2")
D.window.open("http://www.w3cschool.cn","window2")
18.如何在浏览器的状态栏放入一条消息?()
A.statusbar = "put your message here"
B.window.status = "put your message here"
C.window.status("put your message here")
D.status("put your message here")
19.如何获得客户端浏览器的名称?()
A.client.navName
B.navigator.appName
C.browser.name
20.外部脚本必须包含 <script> 标签。()
A.正确
B.错误
请把你的答案写在留言区。^_^
者:Mark A
译者:前端小智
来源:dev
在理解undefined和null之间的差异之前,我们先来看看它们的相似类。
它们属于 JavaScript 的 7 种基本类型。
let primitiveTypes = ['string','number','null','undefined','boolean','symbol', 'bigint'];
它们是属于虚值,可以使用Boolean(value)或!!value将其转换为布尔值时,值为false。
console.log(!!null); // false
console.log(!!undefined); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
接着来看看它们的区别。
undefined是未指定特定值的变量的默认值,或者没有显式返回值的函数,如:console.log(1),还包括对象中不存在的属性,这些 JS 引擎都会为其分配 undefined 值。
let _thisIsUndefined;
const doNothing = () => {};
const someObj = {
a : "ay",
b : "bee",
c : "si"
};
console.log(_thisIsUndefined); // undefined
console.log(doNothing()); // undefined
console.log(someObj["d"]); // undefined
null是“不代表任何值的值”。null是已明确定义给变量的值。在此示例中,当fs.readFile方法未引发错误时,我们将获得null值。
fs.readFile('path/to/file', (e,data) => {
console.log(e); // 当没有错误发生时,打印 null
if(e){
console.log(e);
}
console.log(data);
});
在比较null和undefined时,我们使用==时得到true,使用===时得到false:
console.log(null == undefined); // true
console.log(null === undefined); // false
&& 也可以叫逻辑与,在其操作数中找到第一个虚值表达式并返回它,如果没有找到任何虚值表达式,则返回最后一个真值表达式。它采用短路来防止不必要的工作。
console.log(false && 1 && []); // false
console.log(" " && true && 5); // 5
使用if语句
const router: Router = Router();
router.get('/endpoint', (req: Request, res: Response) => {
let conMobile: PoolConnection;
try {
//do some db operations
} catch (e) {
if (conMobile) {
conMobile.release();
}
}
});
使用&&操作符
const router: Router = Router();
router.get('/endpoint', (req: Request, res: Response) => {
let conMobile: PoolConnection;
try {
//do some db operations
} catch (e) {
conMobile && conMobile.release()
}
});
||也叫或逻辑或,在其操作数中找到第一个真值表达式并返回它。这也使用了短路来防止不必要的工作。在支持 ES6 默认函数参数之前,它用于初始化函数中的默认参数值。
console.log(null || 1 || undefined); // 1
function logName(name) {
var n = name || "Mark";
console.log(n);
}
logName(); // "Mark"
根据MDN文档,+是将字符串转换为数字的最快方法,因为如果值已经是数字,它不会执行任何操作。
DOM 代表文档对象模型,是 HTML 和 XML 文档的接口(API)。当浏览器第一次读取(解析)HTML文档时,它会创建一个大对象,一个基于 HTM L文档的非常大的对象,这就是DOM。它是一个从 HTML 文档中建模的树状结构。DOM 用于交互和修改DOM结构或特定元素或节点。
假设我们有这样的 HTML 结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document Object Model</title>
</head>
<body>
<div>
<p>
<span></span>
</p>
<label></label>
<input>
</div>
</body>
</html>
等价的DOM是这样的:
JS 中的document对象表示DOM。它为我们提供了许多方法,我们可以使用这些方法来选择元素来更新元素内容,等等。
当事件发生在DOM元素上时,该事件并不完全发生在那个元素上。在“冒泡阶段”中,事件冒泡或向上传播至父级,祖父母,祖父母或父级,直到到达window为止;而在“捕获阶段”中,事件从window开始向下触发元素 事件或event.target。
事件传播有三个阶段:
当事件发生在DOM元素上时,该事件并不完全发生在那个元素上。在冒泡阶段,事件冒泡,或者事件发生在它的父代,祖父母,祖父母的父代,直到到达window为止。
假设有如下的 HTML 结构:
<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
对应的 JS 代码:
function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return;
if (typeof el === 'string') {
el = document.querySelector(el);
};
el.addEventListener(event, callback, isCapture);
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child');
const parent = document.querySelector('.parent');
const grandparent = document.querySelector('.grandparent');
addEvent(child, 'click', function (e) {
console.log('child');
});
addEvent(parent, 'click', function (e) {
console.log('parent');
});
addEvent(grandparent, 'click', function (e) {
console.log('grandparent');
});
addEvent(document, 'click', function (e) {
console.log('document');
});
addEvent('html', 'click', function (e) {
console.log('html');
})
addEvent(window, 'click', function (e) {
console.log('window');
})
});
addEventListener方法具有第三个可选参数useCapture,其默认值为false,事件将在冒泡阶段中发生,如果为true,则事件将在捕获阶段中发生。如果单击child元素,它将分别在控制台上记录child,parent,grandparent,html,document和window,这就是事件冒泡。
当事件发生在 DOM 元素上时,该事件并不完全发生在那个元素上。在捕获阶段,事件从window开始,一直到触发事件的元素。
假设有如下的 HTML 结构:
<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
对应的 JS 代码:
function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return;
if (typeof el === 'string') {
el = document.querySelector(el);
};
el.addEventListener(event, callback, isCapture);
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child');
const parent = document.querySelector('.parent');
const grandparent = document.querySelector('.grandparent');
addEvent(child, 'click', function (e) {
console.log('child');
});
addEvent(parent, 'click', function (e) {
console.log('parent');
});
addEvent(grandparent, 'click', function (e) {
console.log('grandparent');
});
addEvent(document, 'click', function (e) {
console.log('document');
});
addEvent('html', 'click', function (e) {
console.log('html');
})
addEvent(window, 'click', function (e) {
console.log('window');
})
});
addEventListener方法具有第三个可选参数useCapture,其默认值为false,事件将在冒泡阶段中发生,如果为true,则事件将在捕获阶段中发生。如果单击child元素,它将分别在控制台上打印window,document,html,grandparent和parent,这就是事件捕获。
event.preventDefault() 方法可防止元素的默认行为。如果在表单元素中使用,它将阻止其提交。如果在锚元素中使用,它将阻止其导航。如果在上下文菜单中使用,它将阻止其显示或显示。event.stopPropagation()方法用于阻止捕获和冒泡阶段中当前事件的进一步传播。
我们可以在事件对象中使用event.defaultPrevented属性。它返回一个布尔值用来表明是否在特定元素中调用了event.preventDefault()。
const obj = {};
console.log(obj.someprop.x);
显然,由于我们尝试访问someprop属性中的x属性,而 someprop 并没有在对象中,所以值为 undefined。记住对象本身不存在的属性,并且其原型的默认值为undefined。因为undefined没有属性x,所以试图访问将会报错。
简单来说,event.target是发生事件的元素或触发事件的元素。
假设有如下的 HTML 结构:
<div onclick="clickFunc(event)" style="text-align: center;margin:15px;
border:1px solid red;border-radius:3px;">
<div style="margin: 25px; border:1px solid royalblue;border-radius:3px;">
<div style="margin:25px;border:1px solid skyblue;border-radius:3px;">
<button style="margin:10px">
Button
</button>
</div>
</div>
</div>
JS 代码如下:
function clickFunc(event) {
console.log(event.target);
}
如果单击 button,即使我们将事件附加在最外面的div上,它也将打印 button 标签,因此我们可以得出结论event.target是触发事件的元素。
event.currentTarget是我们在其上显式附加事件处理程序的元素。
假设有如下的 HTML 结构:
<div onclick="clickFunc(event)" style="text-align: center;margin:15px;
border:1px solid red;border-radius:3px;">
<div style="margin: 25px; border:1px solid royalblue;border-radius:3px;">
<div style="margin:25px;border:1px solid skyblue;border-radius:3px;">
<button style="margin:10px">
Button
</button>
</div>
</div>
</div>
JS 代码如下:
function clickFunc(event) {
console.log(event.currentTarget);
}
如果单击 button,即使我们单击该 button,它也会打印最外面的div标签。在此示例中,我们可以得出结论,event.currentTarget是附加事件处理程序的元素。
==用于一般比较,===用于严格比较,==在比较的时候可以转换数据类型,===严格比较,只要类型不匹配就返回flase。
先来看看 == 这兄弟:
强制是将值转换为另一种类型的过程。在这种情况下,==会执行隐式强制。在比较两个值之前,==需要执行一些规则。
假设我们要比较x == y的值。
注意:toPrimitive首先在对象中使用valueOf方法,然后使用toString方法来获取该对象的原始值。
举个例子。
xyx == y55true1'1'truenullundefinedtrue0falsetrue'1,2'[1,2]true'[object Object]'{}true
这些例子都返回true。
第一个示例符合条件1,因为x和y具有相同的类型和值。
第二个示例符合条件4,在比较之前将y转换为数字。
第三个例子符合条件2。
第四个例子符合条件7,因为y是boolean类型。
第五个示例符合条件8。使用toString()方法将数组转换为字符串,该方法返回1,2。
最后一个示例符合条件8。使用toString()方法将对象转换为字符串,该方法返回[object Object]。
xyx === y55true1'1'falsenullundefinedfalse0falsefalse'1,2'[1,2]false'[object Object]'{}false
如果使用===运算符,则第一个示例以外的所有比较将返回false,因为它们的类型不同,而第一个示例将返回true,因为两者的类型和值相同。
具体更多规则可以对参考我之前的文章:
我对 JS 中相等和全等操作符转化过程一直很迷惑,直到有了这份算法
先看下面的例子:
let a = { a: 1 };
let b = { a: 1 };
let c = a;
console.log(a === b); // 打印 false,即使它们有相同的属性
console.log(a === c); // true
JS 以不同的方式比较对象和基本类型。在基本类型中,JS 通过值对它们进行比较,而在对象中,JS 通过引用或存储变量的内存中的地址对它们进行比较。这就是为什么第一个console.log语句返回false,而第二个console.log语句返回true。a和c有相同的引用地址,而a和b没有。
!!运算符可以将右侧的值强制转换为布尔值,这也是将值转换为布尔值的一种简单方法。
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!''); // false
console.log(!!0); // false
console.log(!!NaN); // false
console.log(!!' '); // true
console.log(!!{}); // true
console.log(!![]); // true
console.log(!!1); // true
console.log(!![].length); // false
可以使用逗号运算符在一行中计算多个表达式。它从左到右求值,并返回右边最后一个项目或最后一个操作数的值。
let x = 5;
x = (x++ , x = addFive(x), x *= 2, x -= 5, x += 10);
function addFive(num) {
return num + 5;
}
上面的结果最后得到x的值为27。首先,我们将x的值增加到6,然后调用函数addFive(6)并将6作为参数传递并将结果重新分配给x,此时x的值为11。之后,将x的当前值乘以2并将其分配给x,x的更新值为22。然后,将x的当前值减去5并将结果分配给x x更新后的值为17。最后,我们将x的值增加10,然后将更新的值分配给x,最终x的值为27。
提升是用来描述变量和函数移动到其(全局或函数)作用域顶部的术语。
为了理解提升,需要来了解一下执行上下文。执行上下文是当前正在执行的“代码环境”。执行上下文有两个阶段:编译和执行。
编译-在此阶段,JS 引荐获取所有函数声明并将其提升到其作用域的顶部,以便我们稍后可以引用它们并获取所有变量声明(使用var关键字进行声明),还会为它们提供默认值:undefined。
执行——在这个阶段中,它将值赋给之前提升的变量,并执行或调用函数(对象中的方法)。
注意:只有使用var声明的变量,或者函数声明才会被提升,相反,函数表达式或箭头函数,let和const声明的变量,这些都不会被提升。
假设在全局使用域,有如下的代码:
console.log(y);
y = 1;
console.log(y);
console.log(greet("Mark"));
function greet(name){
return 'Hello ' + name + '!';
}
var y;
上面分别打印:undefined,1, Hello Mark!。
上面代码在编译阶段其实是这样的:
function greet(name) {
return 'Hello ' + name + '!';
}
var y; // 默认值 undefined
// 等待“编译”阶段完成,然后开始“执行”阶段
/*
console.log(y);
y = 1;
console.log(y);
console.log(greet("Mark"));
*/
编译阶段完成后,它将启动执行阶段调用方法,并将值分配给变量。
function greet(name) {
return 'Hello ' + name + '!';
}
var y;
//start "execution" phase
console.log(y);
y = 1;
console.log(y);
console.log(greet("Mark"));
JavaScript 中的作用域是我们可以有效访问变量或函数的区域。JS 有三种类型的作用域:全局作用域、函数作用域和块作用域(ES6)。
//global namespace
var g = "global";
function globalFunc(){
function innerFunc(){
console.log(g); // can access "g" because "g" is a global variable
}
innerFunc();
}
function myFavoriteFunc(a) {
if (true) {
var b = "Hello " + a;
}
return b;
}
myFavoriteFunc("World");
console.log(a); // Throws a ReferenceError "a" is not defined
console.log(b); // does not continue here
function testBlock(){
if(true){
let z = 5;
}
return z;
}
testBlock(); // Throws a ReferenceError "z" is not defined
作用域也是一组用于查找变量的规则。如果变量在当前作用域中不存在,它将向外部作用域中查找并搜索,如果该变量不存在,它将再次查找直到到达全局作用域,如果找到,则可以使用它,否则引发错误,这种查找过程也称为作用域链。
/* 作用域链
内部作用域->外部作用域-> 全局作用域
*/
// 全局作用域
var variable1 = "Comrades";
var variable2 = "Sayonara";
function outer(){
// 外部作用域
var variable1 = "World";
function inner(){
// 内部作用域
var variable2 = "Hello";
console.log(variable2 + " " + variable1);
}
inner();
}
outer(); // Hello World
这可能是所有问题中最难的一个问题,因为闭包是一个有争议的话题,这里从个人角度来谈谈,如果不妥,多多海涵。
闭包就是一个函数在声明时能够记住当前作用域、父函数作用域、及父函数作用域上的变量和参数的引用,直至通过作用域链上全局作用域,基本上闭包是在声明函数时创建的作用域。
看看小例子:
// 全局作用域
var globalVar = "abc";
function a(){
console.log(globalVar);
}
a(); // "abc"
在此示例中,当我们声明a函数时,全局作用域是a闭包的一部分。
变量globalVar在图中没有值的原因是该变量的值可以根据调用函数a的位置和时间而改变。但是在上面的示例中,globalVar变量的值为abc。
来看一个更复杂的例子:
var globalVar = "global";
var outerVar = "outer"
function outerFunc(outerParam) {
function innerFunc(innerParam) {
console.log(globalVar, outerParam, innerParam);
}
return innerFunc;
}
const x = outerFunc(outerVar);
outerVar = "outer-2";
globalVar = "guess"
x("inner");
上面打印结果是 guess outer inner。
当我们调用outerFunc函数并将返回值innerFunc函数分配给变量x时,即使我们为outerVar变量分配了新值outer-2,outerParam也继续保留outer值,因为重新分配是在调用outerFunc之后发生的,并且当我们调用outerFunc函数时,它会在作用域链中查找outerVar的值,此时的outerVar的值将为 "outer"。
现在,当我们调用引用了innerFunc的x变量时,innerParam将具有一个inner值,因为这是我们在调用中传递的值,而globalVar变量值为guess,因为在调用x变量之前,我们将一个新值分配给globalVar。
下面这个示例演示没有理解好闭包所犯的错误:
const arrFuncs = [];
for(var i = 0; i < 5; i++){
arrFuncs.push(function (){
return i;
});
}
console.log(i); // i is 5
for (let i = 0; i < arrFuncs.length; i++) {
console.log(arrFuncs[i]()); // 都打印 5
}
由于闭包,此代码无法正常运行。var关键字创建一个全局变量,当我们 push 一个函数时,这里返回的全局变量i。因此,当我们在循环后在该数组中调用其中一个函数时,它会打印5,因为我们得到i的当前值为5,我们可以访问它,因为它是全局变量。
因为闭包在创建变量时会保留该变量的引用而不是其值。我们可以使用IIFES或使用 let 来代替 var 的声明。
const falsyValues = ['', 0, null, undefined, NaN, false];
简单的来说虚值就是是在转换为布尔值时变为 false 的值。
使用 Boolean 函数或者 !! 运算符。
"use strict" 是 ES5 特性,它使我们的代码在函数或整个脚本中处于严格模式。严格模式帮助我们在代码的早期避免 bug,并为其添加限制。
严格模式的一些限制:
设立”严格模式”的目的,主要有以下几个:
基本上,this指的是当前正在执行或调用该函数的对象的值。this值的变化取决于我们使用它的上下文和我们在哪里使用它。
const carDetails = {
name: "Ford Mustang",
yearBought: 2005,
getName(){
return this.name;
},
isRegistered: true
};
console.log(carDetails.getName()); // Ford Mustang
这通常是我们期望结果的,因为在getName方法中我们返回this.name,在此上下文中,this指向的是carDetails对象,该对象当前是执行函数的“所有者”对象。
接下我们做些奇怪的事情:
var name = "Ford Ranger";
var getCarName = carDetails.getName;
console.log(getCarName()); // Ford Ranger
上面打印Ford Ranger,这很奇怪,因为在第一个console.log语句中打印的是Ford Mustang。这样做的原因是getCarName方法有一个不同的“所有者”对象,即window对象。在全局作用域中使用var关键字声明变量会在window对象中附加与变量名称相同的属性。请记住,当没有使用“use strict”时,在全局作用域中this指的是window对象。
console.log(getCarName === window.getCarName); // true
console.log(getCarName === this.getCarName); // true
本例中的this和window引用同一个对象。
解决这个问题的一种方法是在函数中使用apply和call方法。
console.log(getCarName.apply(carDetails)); // Ford Mustang
console.log(getCarName.call(carDetails)); // Ford Mustang
apply和call方法期望第一个参数是一个对象,该对象是函数内部this的值。
IIFE或立即执行的函数表达式,在全局作用域内声明的函数,对象内部方法中的匿名函数和内部函数的this具有默认值,该值指向window对象。
(function (){
console.log(this);
})(); // 打印 "window" 对象
function iHateThis(){
console.log(this);
}
iHateThis(); // 打印 "window" 对象
const myFavoriteObj = {
guessThis(){
function getName(){
console.log(this.name);
}
getName();
},
name: 'Marko Polo',
thisIsAnnoying(callback){
callback();
}
};
myFavoriteObj.guessThis(); // 打印 "window" 对象
myFavoriteObj.thisIsAnnoying(function (){
console.log(this); // 打印 "window" 对象
});
如果我们要获取myFavoriteObj对象中的name属性(即Marko Polo)的值,则有两种方法可以解决此问题。
一种是将 this 值保存在变量中。
const myFavoriteObj = {
guessThis(){
const self = this; // 把 this 值保存在 self 变量中
function getName(){
console.log(self.name);
}
getName();
},
name: 'Marko Polo',
thisIsAnnoying(callback){
callback();
}
};
第二种方式是使用箭头函数
const myFavoriteObj = {
guessThis(){
const getName = () => {
console.log(this.name);
}
getName();
},
name: 'Marko Polo',
thisIsAnnoying(callback){
callback();
}
};
箭头函数没有自己的 this。它复制了这个封闭的词法作用域中this值,在这个例子中,this值在getName内部函数之外,也就是myFavoriteObj对象。
简单地说,原型就是对象的蓝图。如果它存在当前对象中,则将其用作属性和方法的回退。它是在对象之间共享属性和功能的方法,这也是JavaScript实现继承的核心。
const o = {};
console.log(o.toString()); // logs [object Object]
即使o对象中不存在o.toString方法,它也不会引发错误,而是返回字符串[object Object]。当对象中不存在属性时,它将查看其原型,如果仍然不存在,则将其查找到原型的原型,依此类推,直到在原型链中找到具有相同属性的属性为止。原型链的末尾是Object.prototype。
console.log(o.toString === Object.prototype.toString); // logs true
由于篇幅过长,我将此系列分成上中下三篇,下篇我们在见。
原文:
https://dev.to/macmacky/70-javascript-interview-questions-5gfi#1-whats-the-difference-between-undefined-and-null
const arr = [1,1,1,1,1,1,3,3,3,3,32,2,2,2,2,3,3,4,-1,-10,-10,-1,4,4,5,5,9]
// set方式去重
// 不改变源数组的数据
console.log([...new Set(arr)])
// includes方式去重, 时间复杂度 O(n)
function uniq(arr) {
let _result = []
for(let i=0; i < arr.length; i++) {
if (!_result.includes(arr[i])) {
_result.push(arr[i])
}
}
return _result
}
console.log(uniq(arr))
let arr = [1,2,5,3,1,6,7,3,4,10,12,3,21]
function bubbleSort(arr) {
// 浅克隆, 对外部传入的参数不进行更改, 保证函数是一个纯函数
let _arr = [].concat(arr)
// 核心逻辑
for(let i=0; i<_arr.length -1; i++) {
for(let j=0; j<_arr.length-i-1; j++) {
if (_arr[j] > _arr[j+1]) {
let temp = _arr[j]
_arr[j] = _arr[j + 1]
_arr[j + 1] = temp
}
}
}
return _arr
}
console.log(bubbleSort(arr))
let arr = [300,432,1342,543,23,656,45,6465,4345,232,87,97,754,345]
function quickSort(arr) {
if(arr.length <= 1) {
return arr
}
const pivot = arr[0]
let bigger = []
let smaller = []
for(let i=1; i<arr.length; i++) {
if (arr[i] > pivot) {
bigger.push(arr[i])
}
}
for(let i=1; i<arr.length; i++) {
if (arr[i] < pivot) {
smaller.push(arr[i])
}
}
return quickSort(smaller).concat(pivot, quickSort(bigger))
}
console.log(quickSort(arr))
案例一:
function curry(fn) {
return function() {
let arg = arguments
return function() {
return fn(...arg, ...arguments)
}
}
}
function fn(a,b,c,d) {
return a+b+c+d
}
let fun = curry(fn)
let fun2 = fun(1,2,3)
console.log(fun2(5))
案例二:
let fn = a => b => c => a+b+c
console.log(fn(1)(2)(3))
let arr = [0,[3,4,5],[[[[12,5,6,7,54,34],43,34],33]], {a:1}]
function flatten(arr) {
let _arr = []
for(let i=0; i<arr.length; i++) {
const leixing = Object.prototype.toString.call(arr[i])
if (leixing !== '[object Array]') {
_arr.push(arr[i])
} else {
_arr = _arr.concat(flatten(arr[i]))
}
}
return _arr
}
console.log(flatten(arr))
Array.prototype.max = function max() {
console.log(this)
return Math.max.apply(Math, this)
}
let array = [1,2,3,4]
console.log(array.max())
let arr = [1,2,3,[4,5,6], {a:1}]
function deepClone(o) {
if (
typeof o == 'number'
||
typeof o == 'string'
||
typeof o == 'boolean'
||
typeof o == 'undefined'
) {
return o
} else if(Array.isArray(o)) {
let _arr = []
for(let i=0; i<o.length; i++) {
_arr.push(deepClone(o[i]))
}
return _arr
} else if(typeof o == 'object') {
let _o = {}
for(let k in o) {
_o[k] = deepClone(o[k])
}
return _o
}
}
let deep = deepClone(arr)
console.log(arr[3] == deep[3]) // false
// 功能: 传入一个数值, 随机生成指定范围内的样本数据
// 参数: 样本个数
// start: 样本起始数值
// end: 样本结束数值
function sample(num, start, end) {
end -= 1
let _arr = []
while(num != _arr.length){
let data = parseInt(Math.random() * end) + start
if (!_arr.includes(data)) {
_arr.push(data)
}
}
return _arr
}
console.log(sample(30, 2, 32))
// 输出结果
// [
// 9, 27, 18, 28, 24, 13, 31, 11, 6,
// 19, 7, 17, 21, 26, 30, 22, 8, 25,
// 10, 3, 2, 5, 4, 12, 20, 14, 29,
// 15, 32, 23
// ]
字符串反转函数
let str = 'abcde'
function myReverse(str) {
return str.split('').reverse().join('')
}
let res = myReverse(str)
console.log(res)
偏函数的作用: 调用之后能够获得一个特定功能的函数
// 需求: 实现一个检查类型的偏函数
function checkType(type) {
return function(o) {
return Object.prototype.toString.call(o) == `[object ${type}]`
}
}
let checkIsArray = checkType('Array')
console.log(checkIsArray([1,2,3]))
// 输出结果
// true
闭包的特点: 调用永久记住当前作用域的变量
案例一:
var a = 2
function foo() {
var a = 1
function bar() {
console.log(a)
}
bar()
}
foo()
//输出结果
//1
案例二:
var a = 1
function bar() {
console.log(a)
}
(function(fn) {
var a = 2
fn()
})(bar)
// 输出结果
// 1
// 箭头函数this跟定义时上下文永远绑定
// 普通函数的this, 视运行环境而改变
function fun() {
return () => {
console.log(this)
}
}
let laowang = {name: 'laowang'}
let xiaoliu = {name: 'xiaoliu'}
let arrowFun = fun.call(laowang)
arrowFun() // { name: 'laowang' }
arrowFun.call(xiaoliu) // { name: 'laowang' }
arrowFun = arrowFun.bind(xiaoliu)
arrowFun() // { name: 'laowang' }
// 函数非严格模式下实参与实参列表的关系
function fun(a, b) {
a = (typeof a !== 'undefined') ? a : 10
b = (typeof b !== 'undefined') ? b : 20
console.log(a == arguments[0])
console.log(b == arguments[1])
a = 123
b = 456
console.log(a == arguments[0])
console.log(b == arguments[1])
}
fun(1, 2)
// 输出结果
// true
// true
// true
// true
// 函数严格模式下实参与实参列表的关系
function fun(a, b) {
'use strict'
a = (typeof a !== 'undefined') ? a : 10
b = (typeof b !== 'undefined') ? b : 20
console.log(a == arguments[0])
console.log(b == arguments[1])
a = 123
b = 456
console.log(a == arguments[0])
console.log(b == arguments[1])
}
fun(1, 2)
// true
// true
// false
// false
// 函数改良
// 这种方式跟非严格模式下的执行结果是一致的
function fun(a=10, b=20) {
console.log(a == arguments[0])
console.log(b == arguments[1])
a = 123
b = 456
console.log(a == arguments[0])
console.log(b == arguments[1])
}
fun(1, 2)
// true
// true
// false
// false
解释: 变量在定义之后, 但没有声明的情况下, 是暂时不能访问的
// 案例一: 函数后面的默认参数可以访问前面的参数
// 实参其实相当于使用 let来声明一个变量
function foo(a) {
return a + 5
}
function fun(a, b = foo(a)) {
console.log(a + b)
}
fun(1) // 7
fun(1, 2) // 3
// 案例二: 函数后面的参数无法访问前面参数的值
function add(a = b, b) {
return a + b
}
console.log(add(1, 2)) // 3
console.log(add(undefined, 2)) // ReferenceError: Cannot access 'b' before initialization
// 不使用展开运算符
let arr = [1,2,3,4]
let max = Math.max.apply(null,arr)
console.log(max)
// 改进
let arr = [1,2,3,4]
let max = Math.max(...arr)
console.log(max)
参考资料: https://www.runoob.com/js/js-strict.html
use strict解释: 为什么使用严格模式:
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。
另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员。
// 需求: 封装一个迭代器
function arrIterator(arr) {
let i = 0
return {
next: function() {
let done = i > arr.length - 1 ? true : false
let value = !done ? arr[i++] : 'undefined'
return {
done,
value
}
}
}
}
let arr = [1,2,3,4,5]
let iterator = arrIterator(arr)
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
// 输出结果
// { done: false, value: 1 }
// { done: false, value: 2 }
// { done: false, value: 3 }
// { done: false, value: 4 }
// { done: false, value: 5 }
// { done: true, value: 'undefined' }
// 生成器
// 作用: 用于生成迭代器
function *generator(arr) {
for(let i=0; i<arr.length; i++) {
yield arr[i]
}
}
let arr = [1,2,3,4,5]
const arrIterator = generator(arr)
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
// 生成器
// 作用: 用于生成迭代器
// 案例一
function *generator(arr) {
for(let i=0; i<arr.length; i++) {
yield arr[i]
}
}
let arr = [1,2,3,4,5]
const arrIterator = generator(arr)
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
console.log(arrIterator.next())
// 输出结果
// { value: 1, done: false }
// { value: 2, done: false }
// { value: 3, done: false }
// { value: 4, done: false }
// { value: 5, done: false }
// { value: undefined, done: true }
// 案例二
// 生成器可以yield 一个Promise实例对象
function *generator() {
yield sumAfter1000ms(1,2).then(res => console.log(res))
yield sumAfter1000ms(2,2).then(res => console.log(res))
}
function sumAfter1000ms(a,b) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(a+b)
}, 2000)
})
}
const iterator = generator()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
// 输出结果
// { value: Promise { <pending> }, done: false }
// { value: Promise { <pending> }, done: false }
// { value: undefined, done: true }
// 3
// 4
promise作用:
- 解决毁掉地狱的问题
- 使代码调用更加清晰易懂
promise的三种状态:
- pending
- resolve
- reject.
promise特点:
- 使用resolve和reject封装结果回调函数
- Promise的实例会调用.then方法
// 案例一
// 不使用promise的情况
function fun(a, b, cb) {
setTimeout(function(){
return cb(a + b)
}, 2000)
}
fun(1,2, res => {
console.log(res)
fun(3,4, res => {
console.log(res)
fun(4, 5, res => {
console.log(res)
})
})
})
// 案例二: 使用promise的写法
function sum(a,b) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(a + b)
}, 2000)
})
}
sum(1,2)
.then(res => {
console.log(res)
})
// 案例三: 使用promise写法封装一个读文件操作函数
const fs = require('fs')
function readFile(filename) {
return new Promise((resolve, reject) => {
fs.readFile(filename, (err, res) => {
if (err) {
reject(new Error('所读的文件不存在'))
return
}
resolve(res.toString())
})
})
}
readFile('./1.txt').then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
*请认真填写需求信息,我们会在24小时内与您取得联系。