一往无前!JS面试必备技能大解密
2023-11-25 12:15:19
JS中的函数、作用域、闭包、原型链和事件循环
在充满活力的JS世界中,深入理解函数、作用域、闭包、原型链和事件循环至关重要。让我们开启一场探索之旅,了解这些概念如何塑造JS的运行方式。
函数定义方式
JS提供了几种定义函数的方法。最直接的方法是使用函数声明 :
function myFunction(x, y) {
return x + y;
}
或者,我们可以使用函数表达式 :
var myFunction = function(x, y) {
return x + y;
};
需要注意的是,Function构造函数 并非定义函数的最佳实践,因为它需要解析两次代码,降低性能。
作用域
JS中的作用域决定了变量和函数的可访问性。全局作用域 包含所有可以在整个程序中访问的变量和函数,而局部作用域 限制变量和函数的访问范围在函数内部。
var globalVariable = 1;
function myFunction() {
var localVariable = 2;
}
在这个例子中,globalVariable
在全局作用域中,而localVariable
仅在myFunction
函数内部可见。
闭包
闭包是在函数内部定义的函数,它能够访问函数内部和外部的变量。即使外部函数已执行完毕,闭包仍保留对这些变量的访问权限。
function outerFunction() {
var outerVariable = 1;
function innerFunction() {
var innerVariable = 2;
console.log(outerVariable); // 输出: 1
console.log(innerVariable); // 输出: 2
}
return innerFunction;
}
var innerFunction = outerFunction();
innerFunction(); // 输出: 1, 2
闭包常用于模拟私有变量和私有方法,弥补了JS缺乏真正私有属性的缺陷。
原型链
JS中的每个对象都有一个原型对象 ,它包含该对象的属性和方法。当对象访问不存在的属性或方法时,JS会自动在其原型对象中查找,依次向上直至找到该属性或方法,或到达根原型对象Object
。
var object1 = {
name: "John"
};
var object2 = Object.create(object1);
console.log(object2.name); // 输出: John
在这个例子中,object2
的原型对象是object1
,因此object2
可以访问object1
的name
属性。
事件循环
JS的事件循环 是一个处理任务的队列。JS引擎从队列中取出任务,并按照先进先出的原则执行它们。
console.log("Hello");
setTimeout(function() {
console.log("World");
}, 0);
console.log("!");
在这个例子中,console.log("Hello")
和console.log("!")
会立即执行,而setTimeout
函数被添加到事件队列中。JS引擎会先执行console.log("Hello")
和console.log("!")
,然后执行console.log("World")
。
常见问题解答
-
什么是函数提升?
函数声明会提升到当前作用域的顶部,因此可以在声明之前调用。 -
如何创建私有变量?
可以使用闭包模拟私有变量,方法是在函数内部定义一个变量,然后返回一个函数来访问该变量。 -
为什么闭包会造成内存泄漏?
闭包会持有对外部函数变量的引用,即使外部函数已执行完毕。这可能导致内存泄漏,如果外部变量不再需要,就必须手动释放引用。 -
原型链如何帮助实现继承?
通过将对象设置为另一个对象的原型,我们可以实现继承。子对象将继承父对象的属性和方法,并可以添加自己的属性和方法。 -
事件循环中的宏任务和微任务有什么区别?
宏任务是在事件循环的一个单独步骤中执行的任务,例如setTimeout
。微任务是在事件循环的当前步骤中执行的任务,例如Promise
。