为了面试能通过,我要看完这75道面试题(下)(1)

function callApi() {

return fetch(“url/to/api/endpoint”)

.then(resp => resp.json())

.then(data => {

//do something with “data”

}).catch(err => {

//do something with “err”

});

}

使用async/await

async/await,我们使用 tru/catch 语法来捕获异常。

async function callApi() {

try {

const resp = await fetch(“url/to/api/endpoint”);

const data = await resp.json();

//do something with “data”

} catch (e) {

//do something with “err”

}

}

注意:使用 async关键声明函数会隐式返回一个Promise

const giveMeOne = async () => 1;

giveMeOne()

.then((num) => {

console.log(num); // logs 1

});

注意:await关键字只能在async function中使用。在任何非async function的函数中使用await关键字都会抛出错误。await关键字在执行下一行代码之前等待右侧表达式(可能是一个Promise)返回。

const giveMeOne = async () => 1;

function getOne() {

try {

const num = await giveMeOne();

console.log(num);

} catch (e) {

console.log(e);

}

}

// Uncaught SyntaxError: await is only valid in async function

async function getTwo() {

try {

const num1 = await giveMeOne(); // 这行会等待右侧表达式执行完成

const num2 = await giveMeOne();

return num1 + num2;

} catch (e) {

console.log(e);

}

}

await getTwo(); // 2

52. 展开(spread )运算符和 剩余(Rest) 运算符有什么区别?

展开运算符(spread)是三个点(...),可以将一个数组转为用逗号分隔的参数序列。说的通俗易懂点,有点像化骨绵掌,把一个大元素给打散成一个个单独的小元素。

剩余运算符也是用三个点(...)表示,它的样子看起来和展开操作符一样,但是它是用于解构数组和对象。在某种程度上,剩余元素和展开元素相反,展开元素会“展开”数组变成多个元素,剩余元素会收集多个元素和“压缩”成一个单一的元素。

function add(a, b) {

return a + b;

};

const nums = [5, 6];

const sum = add(…nums);

console.log(sum);

在本例中,我们在调用add函数时使用了展开操作符,对nums数组进行展开。所以参数a的值是5b的值是6,所以sum11

function add(…rest) {

return rest.reduce((total,current) => total + current);

};

console.log(add(1, 2)); // 3

console.log(add(1, 2, 3, 4, 5)); // 15

在本例中,我们有一个add函数,它接受任意数量的参数,并将它们全部相加,然后返回总数。

const [first, …others] = [1, 2, 3, 4, 5];

console.log(first); // 1

console.log(others); // [2,3,4,5]

这里,我们使用剩余操作符提取所有剩余的数组值,并将它们放入除第一项之外的其他数组中。

53. 什么是默认参数?

默认参数是在 JS 中定义默认变量的一种新方法,它在ES6或ECMAScript 2015版本中可用。

//ES5 Version

function add(a,b){

a = a || 0;

b = b || 0;

return a + b;

}

//ES6 Version

function add(a = 0, b = 0){

return a + b;

}

add(1); // returns 1

我们还可以在默认参数中使用解构。

function getFirst([first, …rest] = [0, 1]) {

return first;

}

getFirst(); // 0

getFirst([10,20,30]); // 10

function getArr({ nums } = { nums: [1, 2, 3, 4] }){

return nums;

}

getArr(); // [1, 2, 3, 4]

getArr({nums:[5,4,3,2,1]}); // [5,4,3,2,1]

我们还可以使用先定义的参数再定义它们之后的参数。

function doSomethingWithValue(value = “Hello World”, callback = () => { console.log(value) }) {

callback();

}

doSomethingWithValue(); //“Hello World”

54. 什么是包装对象(wrapper object)?

我们现在复习一下JS的数据类型,JS数据类型被分为两大类,基本类型引用类型

基本类型:Undefined,Null,Boolean,Number,String,Symbol,BigInt

引用类型:Object,Array,Date,RegExp等,说白了就是对象。

其中引用类型有方法和属性,但是基本类型是没有的,但我们经常会看到下面的代码:

let name = “marko”;

console.log(typeof name); // “string”

console.log(name.toUpperCase()); // “MARKO”

name类型是 string,属于基本类型,所以它没有属性和方法,但是在这个例子中,我们调用了一个toUpperCase()方法,它不会抛出错误,还返回了对象的变量值。

原因是基本类型的值被临时转换或强制转换为对象,因此name变量的行为类似于对象。 除nullundefined之外的每个基本类型都有自己包装对象。也就是:StringNumberBooleanSymbolBigInt。 在这种情况下,name.toUpperCase()在幕后看起来如下:

console.log(new String(name).toUpperCase()); // “MARKO”

在完成访问属性或调用方法之后,新创建的对象将立即被丢弃。

55. 隐式和显式转换有什么区别)?

隐式强制转换是一种将值转换为另一种类型的方法,这个过程是自动完成的,无需我们手动操作。

假设我们下面有一个例子。

console.log(1 + ‘6’); // 16

console.log(false + true); // 1

console.log(6 * ‘2’); // 12

第一个console.log语句结果为16。在其他语言中,这会抛出编译时错误,但在 JS 中,1被转换成字符串,然后与+运算符连接。我们没有做任何事情,它是由 JS 自动完成。

第二个console.log语句结果为1,JS 将false转换为boolean 值为 0,,true1,因此结果为1

第三个console.log语句结果12,它将'2'转换为一个数字,然后乘以6 * 2,结果是12。

而显式强制是将值转换为另一种类型的方法,我们需要手动转换。

console.log(1 + parseInt(‘6’));

在本例中,我们使用parseInt函数将'6'转换为number ,然后使用+运算符将16相加。

56. 什么是NaN? 以及如何检查值是否为NaN?

NaN表示**“非数字”**是 JS 中的一个值,该值是将数字转换或执行为非数字值的运算结果,因此结果为NaN

let a;

console.log(parseInt(‘abc’)); // NaN

console.log(parseInt(null)); // NaN

console.log(parseInt(undefined)); // NaN

console.log(parseInt(++a)); // NaN

console.log(parseInt({} * 10)); // NaN

console.log(parseInt(‘abc’ - 2)); // NaN

console.log(parseInt(0 / 0)); // NaN

console.log(parseInt(‘10a’ * 10)); // NaN

JS 有一个内置的isNaN方法,用于测试值是否为isNaN值,但是这个函数有一个奇怪的行为。

console.log(isNaN()); // true

console.log(isNaN(undefined)); // true

console.log(isNaN({})); // true

console.log(isNaN(String(‘a’))); // true

console.log(isNaN(() => { })); // true

所有这些console.log语句都返回true,即使我们传递的值不是NaN

ES6中,建议使用Number.isNaN方法,因为它确实会检查该值(如果确实是NaN),或者我们可以使自己的辅助函数检查此问题,因为在 JS 中,NaN是唯一的值,它不等于自己。

function checkIfNaN(value) {

return value !== value;

}

57. 如何判断值是否为数组?

我们可以使用Array.isArray方法来检查值是否为数组。 当传递给它的参数是数组时,它返回true,否则返回false

console.log(Array.isArray(5)); // false

console.log(Array.isArray(“”)); // false

console.log(Array.isArray()); // false

console.log(Array.isArray(null)); // false

console.log(Array.isArray({ length: 5 })); // false

console.log(Array.isArray([])); // true

如果环境不支持此方法,则可以使用polyfill实现。

function isArray(value){

return Object.prototype.toString.call(value) === “[object Array]”

}

当然还可以使用传统的方法:

let a = []

if (a instanceof Array) {

console.log(‘是数组’)

} else {

console.log(‘非数组’)

}

58. 如何在不使用%模运算符的情况下检查一个数字是否是偶数?

我们可以对这个问题使用按位&运算符,&对其操作数进行运算,并将其视为二进制值,然后执行与运算。

function isEven(num) {

if (num & 1) {

return false

} else {

return true

}

}

0 二进制数是 000

1 二进制数是 001

2 二进制数是 010

3 二进制数是 011

4 二进制数是 100

5 二进制数是 101

6 二进制数是 110

7 二进制数是 111

以此类推…

与运算的规则如下:

| a | b | a & b |

| :-- | :-- | :-- |

| 0 | 0 | 0 |

| 0 | 1 | 0 |

| 1 | 1 | 1 |

因此,当我们执行console.log(5&1)这个表达式时,结果为1。首先,&运算符将两个数字都转换为二进制,因此5变为1011变为001

然后,它使用按位怀运算符比较每个位(01)。 101&001,从表中可以看出,如果a & b1,所以5&1结果为1

| 101 & 001 |

| — |

| 101 |

| 001 |

| 001 |

  • 首先我们比较最左边的1&0,结果是0

  • 然后我们比较中间的0&0,结果是0

  • 然后我们比较最后1&1,结果是1

  • 最后,得到一个二进制数001,对应的十进制数,即1

由此我们也可以算出console.log(4 & 1) 结果为0。知道4的最后一位是0,而0 & 1 将是0。如果你很难理解这一点,我们可以使用递归函数来解决此问题。

function isEven(num) {

if (num < 0 || num === 1) return false;

if (num == 0) return true;

return isEven(num - 2);

}

59. 如何检查对象中是否存在某个属性?

检查对象中是否存在属性有三种方法。

第一种使用 in 操作符号:

const o = {

“prop” : “bwahahah”,

“prop2” : “hweasa”

};

console.log(“prop” in o); // true

console.log(“prop1” in o); // false

第二种使用 hasOwnProperty 方法,hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。

console.log(o.hasOwnProperty(“prop2”)); // true

console.log(o.hasOwnProperty(“prop1”)); // false

第三种使用括号符号obj["prop"]。如果属性存在,它将返回该属性的值,否则将返回undefined

console.log(o[“prop”]); // “bwahahah”

console.log(o[“prop1”]); // undefined

60. AJAX 是什么?

即异步的 JavaScript 和 XML,是一种用于创建快速动态网页的技术,传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。使用AJAX则不需要加载更新整个网页,实现部分内容更新

用到AJAX的技术:

  • HTML - 网页结构

  • CSS - 网页的样式

  • JavaScript - 操作网页的行为和更新DOM

  • XMLHttpRequest API - 用于从服务器发送和获取数据

  • PHP,Python,Nodejs - 某些服务器端语言

61. 如何在 JS 中创建对象?

使用对象字面量:

const o = {

name: “前端小智”,

greeting() {

return Hi, 我是${this.name};

}

};

o.greeting(); // “Hi, 我是前端小智”

使用构造函数:

function Person(name) {

this.name = name;

}

Person.prototype.greeting = function () {

return Hi, 我是${this.name};

}

const mark = new Person(“前端小智”);

mark.greeting(); // “Hi, 我是前端小智”

使用 Object.create 方法:

const n = {

greeting() {

return Hi, 我是${this.name};

}

};

const o = Object.create(n);

o.name = “前端小智”;

62. Object.seal 和 Object.freeze 方法之间有什么区别?

Object.freeze()

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

Object.seal()

Object.seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。

方法的相同点:

  1. ES5新增。

  2. 对象不可能扩展,也就是不能再添加新的属性或者方法。

  3. 对象已有属性不允许被删除。

  4. 对象属性特性不可以重新配置。

方法不同点:

  • Object.seal方法生成的密封对象,如果属性是可写的,那么可以修改属性值。

* Object.freeze方法生成的冻结对象,属性都是不可写的,也就是属性值无法更改。

63. in 运算符和 Object.hasOwnProperty 方法有什么区别?

hasOwnPropert方法

hasOwnPropert()方法返回值是一个布尔值,指示对象自身属性中是否具有指定的属性,因此这个方法会忽略掉那些从原型链上继承到的属性。

看下面的例子:

Object.prototype.phone= ‘15345025546’;

let obj = {

name: ‘前端小智’,

age: ‘28’

}

console.log(obj.hasOwnProperty(‘phone’)) // false

console.log(obj.hasOwnProperty(‘name’)) // true

可以看到,如果在函数原型上定义一个变量phonehasOwnProperty方法会直接忽略掉。

in 运算符

如果指定的属性在指定的对象或其原型链中,则in 运算符返回true

还是用上面的例子来演示:

console.log(‘phone’ in obj) // true

可以看到in运算符会检查它或者其原型链是否包含具有指定名称的属性。

64. 有哪些方法可以处理 JS 中的异步代码?

  • 回调

  • Promise

  • async/await

  • 还有一些库: async.js, bluebird, q, co

65. 函数表达式和函数声明之间有什么区别?

看下面的例子:

hoistedFunc();

notHoistedFunc();

function hoistedFunc(){

console.log(“注意:我会被提升”);

}

var notHoistedFunc = function(){

console.log(“注意:我没有被提升”);

}

notHoistedFunc调用抛出异常:Uncaught TypeError: notHoistedFunc is not a function,而hoistedFunc调用不会,因为hoistedFunc会被提升到作用域的顶部,而notHoistedFunc 不会。

66. 调用函数,可以使用哪些方法?

在 JS 中有4种方法可以调用函数。

作为函数调用——如果一个函数没有作为方法、构造函数、applycall 调用时,此时 this 指向的是 window 对象(非严格模式)

//Global Scope

function add(a,b){

console.log(this);

return a + b;

}

add(1,5); // 打印 “window” 对象和 6

const o = {

method(callback){

callback();

}

}

o.method(function (){

console.log(this); // 打印 “window” 对象

});

作为方法调用——如果一个对象的属性有一个函数的值,我们就称它为方法。调用该方法时,该方法的this值指向该对象。

const details = {

name : “Marko”,

getName(){

return this.name;

}

}

details.getName(); // Marko

作为构造函数的调用-如果在函数之前使用new关键字调用了函数,则该函数称为构造函数。构造函数里面会默认创建一个空对象,并将this指向该对象。

function Employee(name, position, yearHired) {

// 创建一个空对象 {}

// 然后将空对象分配给“this”关键字

// this = {};

this.name = name;

this.position = position;

this.yearHired = yearHired;

// 如果没有指定 return ,这里会默认返回 this

};

const emp = new Employee(“Marko Polo”, “Software Developer”, 2017);

使用applycall方法调用——如果我们想显式地指定一个函数的this值,我们可以使用这些方法,这些方法对所有函数都可用。

const obj1 = {

result:0

};

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

details.getName(); // Marko

作为构造函数的调用-如果在函数之前使用new关键字调用了函数,则该函数称为构造函数。构造函数里面会默认创建一个空对象,并将this指向该对象。

function Employee(name, position, yearHired) {

// 创建一个空对象 {}

// 然后将空对象分配给“this”关键字

// this = {};

this.name = name;

this.position = position;

this.yearHired = yearHired;

// 如果没有指定 return ,这里会默认返回 this

};

const emp = new Employee(“Marko Polo”, “Software Developer”, 2017);

使用applycall方法调用——如果我们想显式地指定一个函数的this值,我们可以使用这些方法,这些方法对所有函数都可用。

const obj1 = {

result:0

};

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-MHeC0MIZ-1715806211094)]

[外链图片转存中…(img-9Zle8EnV-1715806211095)]

[外链图片转存中…(img-xDDs0LzW-1715806211095)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值