什么是window对象? 什么是document对象?
window对象是浏览器环境提供的全局对象,它代表了当前浏览器窗口(或者标签页)。在浏览器中,window对象是 JavaScript 全局对象的最高层级,它包含了浏览器的窗口、浏览器的标签页和其他相关的属性和方法。因此,可以使用window对象来访问或操作浏览器窗口的各种功能和属性。在全局作用域中,window对象作为默认的上下文对象,也可以省略不写。document对象是window对象的一个属性,代表了当前页面的 DOM (文档对象模型)。document对象可以用于访问和操作网页中的元素、样式、内容等。它提供了一系列的方法和属性,用于搜索、创建、修改和删除网页中的 HTML 元素。document对象是与网页交互的主要接口之一,通过它可以动态地修改网页的结构和内容。例如,可以使用document.getElementById()、document.querySelector()等方法选中元素,或者使用document.createElement()、document.createTextNode()等方法创建新的元素和文本节点。
综上所述,window 对象代表了整个浏览器窗口,而 document 对象代表了当前页面的 DOM 结构,两者可以通过 JavaScript 进行交互和操作。
[“1”, “2”, “3”].map(parseInt) 答案是多少?
答案是 [1, NaN, NaN]。
Array.prototype.map() 方法接受一个函数作为参数,并将该函数应用于数组的每个元素。在这个例子中,我们使用了 parseInt 函数作为 map 的参数。
然而,需要注意的是,parseInt 函数接受两个参数:要解析的字符串和基数(进制数)。而在 map 中,parseInt 函数被作为回调函数,被传递了三个参数:当前元素,当前元素的索引,原数组本身。
对于 ["1", "2", "3"] 这个数组:
- 当
parseInt处理第一个元素"1"时,基数为 0(默认),相当于按十进制处理,返回整数 1。 - 当
parseInt处理第二个元素"2"时,基数为 1,相当于按一进制处理,由于不存在一进制的表示,结果为 NaN。 - 当
parseInt处理第三个元素"3"时,基数为 2,相当于按二进制处理,由于二进制不存在 3 的表示,结果也是 NaN。
因此,["1", "2", "3"].map(parseInt) 的结果是 [1, NaN, NaN]。
什么是闭包(closure),为什么要用它?
闭包(closure)是指函数与其词法环境的组合。简单来说,闭包是由函数及其相关的引用环境组合而成的实体。它在函数内部创建了一个独立的作用域,可以访问函数外部的变量,并且保持对这些变量的引用。
闭包的主要特点
- 函数内部的函数可以访问函数外部的变量,即使在外部函数执行完毕后仍然有效。
- 闭包使得函数内部的数据(变量、参数)被封装起来,不会被外部的函数随意修改。
使用闭包的主要原因
- 封装变量:闭包允许我们封装变量并将其私有化,避免了全局作用域的污染,有助于编写模块化和可维护的代码。
- 数据持久性:通过闭包,可以将数据存储在函数外部的变量中,并保留对这些数据的访问,即使外部函数已经执行完毕。
- 记忆前一个状态:闭包可以记住上一个函数调用时的状态,例如计数器函数中记录执行次数。
- 实现私有成员:利用闭包的特性,可以创建只有内部函数才能访问的私有成员。
- 实现高阶函数:闭包可以作为高阶函数的返回值或参数,用于实现函数柯里化、函数组合等编程技巧。
需要注意的是,闭包也可能带来一些问题,比如内存泄漏问题,如果没有正确释放对外部变量的引用。因此,在使用闭包时需要注意内存管理和性能优化。
模块化开发怎么做?
模块化开发是一种组织和管理代码的方法,可以将代码分割成独立的模块,每个模块负责完成特定的功能。
下面是一些常见的模块化开发方法和实践:
使用立即执行函数表达式(IIFE):通过使用立即执行函数,创建一个独立的作用域,避免变量之间的冲突,并将模块中的代码封装起来。此外,可以通过传递参数的方式,将依赖注入到模块中。
(function() { // 模块的代码 })();
- 使用命名空间:使用对象字面量或命名空间对象,将相关的函数、类和变量组织在一起,并防止全局污染。
var myModule = { // 模块的代码 };
使用 CommonJS 或 AMD(Asynchronous Module Definition)规范:这些规范定义了 JavaScript 模块的导入和导出方式,使得模块间的依赖管理更加清晰和可控。
- CommonJS 示例:
// 导出模块 module.exports = { // 模块的代码 }; // 导入模块 var myModule = require('./myModule');
- AMD 示例:
// 定义模块 define(['dep1', 'dep2'], function(dep1, dep2) { // 模块的代码 return { /* 模块的导出对象 */ }; }); // 导入模块 require(['myModule'], function(myModule) { // 使用模块 });
- 使用 ES6 的模块化语法:ES6 引入了官方的模块化语法,支持导入和导出模块。
- 导出模块:
// 导出命名导出 export const PI = 3.1415; // 导出默认导出 export default function() { /* 模块代码 */ }
- 导入模块:
// 导入命名导出 import { PI, foo } from './myModule'; // 导入默认导出 import myModule from './myModule';
以上只是几种常见的模块化开发方法,根据具体的项目需求和使用的技术栈,可以选择合适的模块化方案。模块化开发有助于提高代码的可维护性、复用性和测试性,同时减少命名冲突和全局变量的污染。
数组和对象有哪些原生方法,列举一下?
JavaScript 中的数组和对象都提供了一些原生方法,用于操作和处理数据。
以下是数组和对象常用的一些原生方法的列举:
数组的原生方法:
push(): 在数组末尾添加一个或多个元素,并返回新数组的长度。pop(): 删除并返回数组的最后一个元素。shift(): 删除并返回数组的第一个元素。unshift(): 在数组的开头添加一个或多个元素,并返回新数组的长度。concat(): 合并两个或多个数组,返回一个新数组。join(): 将数组的所有元素连接成一个字符串。slice(): 从数组中截取指定位置的元素,返回一个新数组。splice(): 在数组中插入、删除或替换元素。indexOf(): 返回数组中第一个匹配元素的索引。forEach(): 对数组中的每个元素执行指定的函数。map(): 对数组中的每个元素执行指定的函数,并返回一个新数组。filter(): 使用指定的函数过滤数组中的元素,并返回一个新数组。reduce(): 对数组中的元素依次执行指定的函数,返回一个累积的结果。sort(): 对数组元素进行排序。reverse(): 反转数组中的元素顺序。isArray(): 检测一个对象是否为数组。
对象的原生方法:
Object.keys(): 返回一个包含对象自身可枚举属性的数组。Object.values(): 返回一个包含对象自身可枚举属性的值的数组。Object.entries(): 返回一个包含对象自身可枚举属性的键值对的数组。Object.assign(): 将一个或多个源对象的属性复制到目标对象。Object.freeze(): 冻结对象,使其属性不可修改。Object.seal(): 封闭对象,使其属性不可添加或删除,但可修改。Object.create(): 创建一个新对象,使用现有的对象作为新对象的原型。Object.hasOwnProperty(): 判断对象是否具有指定的自身属性。
这只是一些常用的数组和对象的原生方法,JavaScript 还提供了其他的一些方法。
根据具体的需求和使用场景,你可以查阅相关文档来了解更多的方法和其用法。