解释JavaScript的数据类型,并举例说明每种类型。
JavaScript有七种数据类型:字符串(String)、数字(Number)、布尔值(Boolean)、对象(Object)、数组(Array)、空值(Null)和未定义(Undefined)。例如:
let str = "Hello";
let num = 10;
let bool = true;
let obj = { name: "John" };
let arr = [1, 2, 3];
let n = null;
let undef;
null,undefined的区别?
null表示一个对象被定义了,但存放了空指针,转换为数值时为0。
undefined表示声明的变量未初始化,转换为数值时为NAN。
typeof(null) -- object;
typeof(undefined) -- undefined
基本数据类型包含字符串(String)、数字(Number)、布尔值(Boolean)、空值(Null),存储在栈中。
引用数据类型包含对象(Object)、数组(Array),存储在堆中,指针放在栈中。
两种类型的区别是:
存储位置不同;原始数据类型直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;引用数据类型存储在堆中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能。
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
栈和堆的区别?
栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量等;
堆(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统释放。
解释JavaScript中的变量提升(Hoisting)是什么。
变量提升是指在JavaScript中,变量和函数声明会在代码执行之前被提升到作用域的顶部。这意味着可以在声明之前使用变量和函数。例如:
console.log(x); // 输出 undefined
var x = 5;
解释JavaScript中的闭包(Closure)是什么,并举例说明。
闭包是指函数可以访问并操作其词法作用域之外的变量。它通过在函数内部创建一个内部函数,并返回该内部函数来实现。例如:
function outer() {
let x = 10;
function inner() {
console.log(x);
}
return inner;
}
let closure = outer();
closure(); // 输出 10
// 创建三个全局变量
let add;
let getCount;
let setCount;
function createCounter() {
let count = 0; // 外部变量
add = () => {count++}
getCount = () => {return count}
setCount = (n) => {count = n}
}
createCounter();
add();
console.log(getCount()); // 打印1
正常情况下,一个函数作用域中定义了一个变量比如x,函数执行完毕后,这个x没被别的变量引用到,那就直接回收,释放内存。
所谓闭包,就是函数作用域中定义的这个变量x,被别的变量y引用了,就不能回收,还要用不是嘛。如果要释放这个内存,就让y这个变量不再引用到x。比如可以让y = null。
有权访问另一个函数作用域内变量的函数都是闭包。
简单的说,javascript允许使用内部函数 ---即函数定义和函数表达式位于另一个函数的函数体内。而且这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
闭包应用场景
(1) 数据封装与私有变量
通过闭包隐藏内部状态,仅暴露操作接口(类似面向对象的私有成员)
(2) 模块化开发(IIFE模式)
利用立即执行函数(IIFE)封装模块,避免全局污染:
(3) 函数工厂与柯里化
生成定制化函数(如固定部分参数):
function multiplyBy(factor) {
return function(num) {
return num * factor; // 闭包保留factor
};
}
const double = multiplyBy(2);
console.log(double(8)); // 16
解释JavaScript中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing)。
事件冒泡是指事件从最具体的元素开始向父元素逐级触发,直到触发到根元素。事件捕获是指事件从根元素开始,逐级向最具体的元素触发。可以使用addEventListener方法的第三个参数来控制是使用事件冒泡还是事件捕获。
解释JavaScript中的原型继承(Prototype Inheritance)是什么。
原型继承是JavaScript中实现对象之间继承关系的一种机制。每个对象都有一个原型对象,它包含了共享的属性和方法。当访问对象的属性或方法时,如果对象本身没有,则会沿着原型链向上查找。可以使用Object.create()方法或设置对象的__proto__属性来实现原型继承。
解释JavaScript中的异步编程,并提供一个异步操作的示例。
异步编程是指在代码执行过程中,不会阻塞后续代码执行的一种编程方式。常见的异步操作包括网络请求、定时器等。例如:
console.log("开始");
setTimeout(function() {
console.log("异步操作");
}, 1000);
console.log("结束");
解释JavaScript中的this关键字的作用和使用场景。
this关键字在JavaScript中表示当前执行上下文的对象。它的具体取值根据函数的调用方式而定。
在全局作用域中,this指向全局对象(浏览器环境中为window对象)。
在函数中,this的指向取决于函数的调用方式,可以通过call、apply、bind等方法来显式地指定this的值。
解释JavaScript中的事件委托(Event Delegation)是什么,并提供一个使用事件委托的示例。
事件委托是指将事件处理程序绑定到父元素上,而不是直接绑定到每个子元素上。当事件触发时,事件会冒泡到父元素,然后通过判断事件的目标来执行相应的处理逻辑。这样可以减少事件处理程序的数量,提高性能。例如:
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script>
document.getElementById("list").addEventListener("click", function(event) {
if (event.target.tagName === "LI") {
console.log(event.target.textContent);
}
});
</script>
解释JavaScript中的模块化编程,并提供一个使用模块的示例。
答案:模块化编程是指将代码划分为独立的模块,每个模块负责特定的功能,并通过导入和导出来实现模块之间的依赖关系。ES6引入了模块化的语法,可以使用import和export关键字来导入和导出模块。例如:
// module.js
export function sayHello() {
console.log("Hello!");
}
// main.js
import { sayHello } from "./module.js";
sayHello(); // 输出 "Hello!"
["1", "2", "3"].map(parseInt) 答案是多少?
[1,NaN,NaN]
解析:
Array.prototype.map()
array.map(callback[, thisArg])
callback函数的执行规则
参数:自动传入三个参数
currentValue(当前被传递的元素);
index(当前被传递的元素的索引);
array(调用map方法的数组)
parseInt方法接收两个参数
第三个参数["1", "2", "3"]将被忽略。parseInt方法将会通过以下方式被调用
parseInt("1", 0)
parseInt("2", 1)
parseInt("3", 2)
parseInt的第二个参数radix为0时,ECMAScript5将string作为十进制数字的字符串解析;
parseInt的第二个参数radix为1时,解析结果为NaN;
parseInt的第二个参数radix在2—36之间时,如果string参数的第一个字符(除空白以外),不属于radix指定进制下的字符,解析结果为NaN。
parseInt("3", 2)执行时,由于"3"不属于二进制字符,解析结果为NaN。
new操作符具体干了什么呢?
- 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
- 属性和方法被加入到 this 引用的对象中。
- 新创建的对象由 this 所引用,并且最后隐式的返回 this 。
Javascript中,执行时对象查找时,永远不会去查找原型的函数?
Object.hasOwnProperty(proName):是用来判断一个对象是否有你给出名称的属性。不过需要注意的是,此方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身的一个成员。