概述
1. 构造函数返回属性时,属性的值为?
function Car(){
this.mark = "L"
return {mark: "M"}
}
const myCar = new Car()
console.log(myCar.mark);
// M
返回属性的时候,属性的值等于返回的值,而不是构造函数中设定的值。
2. 修改引入的模块会怎样?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
// Error
引入的模块是只读的,不能修改,只有导出他们的模块才能修改其值。当我们给myCounter增加一个值的时候会抛出一个异常: myCounter是只读的,不能被修改。
3. delete操作符可以删除哪些?返回什么?
const name = "L"
age = 20
console.log(delete name);
console.log(delete age);
// false
// true
delete操作符返回一个布尔值:true指删除成功,false指删除失败。
delete不能删除由var、let、const声明的变量;name变量由const关键字声明,所以删除不成功:返回 false。
delete可以删除对象的属性,而我们设定age等于21时,我们实际上添加了一个名为age的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以delete age返回true。
4. Object.defineProperty() 的默认不可枚举性
const person = {name: "L"}
Object.defineProperty(person, "age", {value: 21})
console.log(person);
console.log(Object.keys(person));
// {name: "L", age: 21}
// ['name']
通过defineProperty方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用defineProperty方法给对象添加了一个属性之后,属性默认为 不可枚举(not enumerable). Object.keys方法仅返回对象中 可枚举(enumerable) 的属性,因此只剩下了"name".
用defineProperty方法添加的属性默认不可变。你可以通过writable, configurable 和 enumerable属性来改变这一行为。这样的话, 相比于自己添加的属性,defineProperty方法添加的属性有了更多的控制权。
5. JSON.stringify()的第二个参数是?
const settings = {
username: "lydiahallie",
level: 19,
health: 90
};
const data = JSON.stringify(settings, ["level", "health"])
console.log(data);
console.log(typeof data);
// "{level: 19, health: 90}"
// string
JSON.stringify()的第二个参数是 替代者(replacer)。替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。
如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为"level" 和 “health” 的属性被包括进来, "username"则被排除在外。 data 就等于 “{“level”:19, “health”:90}”.
而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。 函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为undefined,则该属性会被排除在外。
6. ES6的函数参数默认值
const value = {number: 10}
const multiply = (x = {...value}) => {
console.log(x.number *= 2);
}
multiply()
multiply()
multiply(value)
multiply(value)
// 20
// 20
// 20
// 40
在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 “undefined” ,那么参数的值将是默认值。上述例子中,我们将 value 对象进行了解构并传到一个新对象中,因此 x 的默认值为 {number:10} 。
默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 multiply 函数且不传递值,那么每一次 x 的默认值都为 {number:10} ,因此打印出该数字的乘积值为20。
第三次调用 multiply 时,我们传递了一个参数,即对象value。 *=运算符实际上是x.number = x.number * 2的简写,我们修改了x.number的值,并打印出值20。
第四次,我们再次传递value对象。 x.number之前被修改为20,所以x.number * = 2打印为40。
7. reduce的参数,acc和cur?
[1,2,3,4].reduce((x,y)=>{console.log(x,y)})
// 1 2
// undefined 3
// undefined 4
reducer 函数接收4个参数:
Accumulator (acc) (累计器)
Current Value (cur) (当前值)
Current Index (idx) (当前索引)
Source Array (src) (源数组)
reducer 函数的返回值将会分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。
reducer 函数还有一个可选参数initialValue, 该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供initialValue,则将使用数组中的第一个元素。
在上述例子,reduce方法接收的第一个参数(Accumulator)是x, 第二个参数(Current Value)是y。
在第一次调用时,累加器x为1,当前值“y”为2,打印出累加器和当前值:1和2。
例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回undefined。 在下一次调用时,累加器为undefined,当前值为“3”, 因此undefined和3被打印出。
在第四次调用时,回调函数依然没有返回值。 累加器再次为 undefined ,当前值为“4”。 undefined和4被打印出。
8. import导入的模块会先运行吗?
// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));
// 'running sum.js'
// 'running index.js'
// 3
// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;
import命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
这是CommonJS中require()和import之间的区别。使用require(),您可以在运行代码时根据需要加载依赖项。 如果我们使用require而不是import,running index.js,running sum.js,3会被依次打印。
9. 异步函数的返回值总是?
async function getData(){
return await Promise.resolve("I made it!")
}
const data = getData()
console.log(data);
// Promise {<pending>}
异步函数始终返回一个promise。await仍然需要等待promise的解决:当我们调用getData()并将其赋值给data,此时data为getData方法返回的一个挂起的promise,该promise并没有解决。
如果我们想要访问已解决的值"I made it!",可以在data上使用.then()方法:
data.then(res => console.log(res))
这样将打印 “I made it!”
10. 没有设置默认值时,函数参数值为?
function sayHi(name) {
return `Hi there, ${name}`
}
console.log(sayHi())
默认情况下,如果不给函数传参,参数的值将为undefined。 上述情况,我们没有给参数name传值。 name等于undefined,并被打印。
在ES6中,我们可以使用默认参数覆盖此默认的undefined值。 例如:
function sayHi(name =“Lydia”){…}
在这种情况下,如果我们没有传递值或者如果我们传递undefined,name总是等于字符串Lydia
11. 注意const、let的块级作用域
function checkAge(age) {
if (age < 18) {
const message = "Sorry, you're too young."
} else {
const message = "Yay! You're old enough!"
}
return message
}
console.log(checkAge(21))
// ReferenceError
const和let声明的变量是具有块级作用域的,块是大括号({})之间的任何东西, 即上述情况if / else语句的花括号。 由于块级作用域,我们无法在声明的块之外引用变量,因此抛出ReferenceError。
12. 函数有多个形参,后面参数的默认值可以为前一个参数?
function sum(num1, num2 = num1) {
console.log(num1 + num2)
}
sum(10)
// 20
您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。 我们将值10传递给sum函数。 如果sum函数只接收1个参数,则意味着没有传递num2的值,这种情况下,num1的值等于传递的值10。 num2的默认值是num1的值,即10。 num1 + num2返回20。
13. 箭头函数有prototype吗?
function fn(){
return "hi"
}
const test = ()=>{return "hello"}
console.log(fn.prototype);
console.log(test.prototype);
// {constructor: f}
// undefined
常规函数,例如fn函数,有一个prototype属性,它是一个带有constructor属性的对象(原型对象)。 然而,箭头函数,例如test函数,没有这个prototype属性。 尝试使用test.prototype访问prototype属性时会返回undefined。
14. ES6的剩余参数
function getItems(fruitList, ...args, favoriteFruit) {
return [...fruitList, ...args, favoriteFruit]
}
getItems(["banana", "apple"], "pear", "orange")
// SyntaxError
… args是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。
15. 此类等于彼类?
class Person {
constructor(){
this.name = "L"
}
}
Person = class AnotherPeron {
constructor(){
this.name = "X"
}
}
const members = new Person()
console.log(members.name);
// X
我们可以将类设置为等于其他类/函数构造函数。 在这种情况下,我们将Person设置为AnotherPerson。 这个构造函数的名字是X,所以新的Person实例members上的name属性是X。
16. Symbol除了表示唯一的值,你还知道什么?
const info = {
[Symbol('a')]: 'b'
}
console.log(info)
console.log(Object.keys(info))
// {Symbol('a'): 'b'}
// []
Symbol类型是不可枚举的。Object.keys方法返回对象上的所有可枚举的键属性。Symbol类型是不可见的,并返回一个空数组。 记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
这是Symbol的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用2个想要向同一对象添加属性的库时),您还可以隐藏这种方式对象的属性(尽管不完全。你仍然可以使用Object.getOwnPropertySymbols()方法访问 Symbol。
17. 箭头函数返回一个对象,还需要加圆括号?
const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }
const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }
console.log(getList(list))
console.log(getUser(user))
// [1,[2,3,4]]
// undefined
getList函数接收一个数组作为其参数。 在getList函数的括号之间,我们立即解构这个数组。 您可以将其视为:
[x, …y] = [1, 2, 3, 4]
使用剩余的参数… y,我们将所有剩余参数放在一个数组中。 在这种情况下,其余的参数是2,3和4。 y的值是一个数组,包含所有其余参数。 在这种情况下,x的值等于1,所以当我们打印[x,y]时,会打印[1,[2,3,4]]。
getUser函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须在圆括号之间编写它,否则不会返回任何值!下面的函数将返回一个对象:
const getUser = user => ({ name: user.name, age: user.age })
由于在这种情况下不返回任何值,因此该函数返回undefined。
最后
以上就是无辜芹菜为你收集整理的JavaScript 进阶小细节-2的全部内容,希望文章能够帮你解决JavaScript 进阶小细节-2所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复