前端面试题详解整理113|CSS盒模型,阻止冒泡,webpack,懒加载,cdn,移动端的适配方案,

135 阅读22分钟

阿里 国际化 LAZADA 挂

  • 英文自我介绍

  • 作用域的概念

作用域(Scope)是指在程序中定义变量的区域,它决定了变量的可见性和访问权限。JavaScript 中的作用域分为全局作用域和局部作用域(也称为函数作用域)。

  1. 全局作用域(Global Scope): 全局作用域是整个程序范围内可访问的作用域,其中定义的变量在整个程序中都是可见的。

    var globalVariable = 'I am in global scope';
    
    function myFunction() {
        console.log(globalVariable); // 可以访问全局作用域中的变量
    }
    
    myFunction(); // 输出 'I am in global scope'
    
  2. 局部作用域(Local Scope): 局部作用域是在函数内部定义的作用域,其中定义的变量只在函数内部可见。

    function myFunction() {
        var localVariable = 'I am in local scope';
        console.log(localVariable); // 可以访问局部作用域中的变量
    }
    
    myFunction(); // 输出 'I am in local scope'
    console.log(localVariable); // 报错,无法访问局部作用域中的变量
    

JavaScript 中的作用域具有以下特点:

  • 作用域链(Scope Chain): 在 JavaScript 中,作用域是嵌套的,内部作用域可以访问外部作用域中定义的变量,但外部作用域不能访问内部作用域中定义的变量。当访问变量时,JavaScript 引擎会沿着作用域链从内向外查找变量。

  • 词法作用域(Lexical Scope): JavaScript 使用词法作用域,也称为静态作用域。这意味着作用域是在编写代码时确定的,而不是在运行时确定的。函数的作用域在函数定义时就已经确定了,而不是在调用时。

作用域的概念对于理解 JavaScript 中变量的生命周期、可见性和闭包等概念非常重要。

this指向

JavaScript 中的 this 关键字在不同的上下文中会指向不同的对象,其指向取决于函数的调用方式。下面是几种常见情况下 this 的指向:

  1. 全局上下文: 在全局上下文中,this 指向全局对象,在浏览器中通常是 window 对象。

  2. 函数调用: 当函数作为普通函数调用时,this 指向全局对象。例如:

    function myFunction() {
        console.log(this);
    }
    
    myFunction(); // 在浏览器中输出 window 对象
    
  3. 对象方法调用: 当函数作为对象的方法调用时,this 指向调用该方法的对象。

    var obj = {
        name: 'John',
        sayHello: function() {
            console.log(this.name);
        }
    };
    
    obj.sayHello(); // 输出 'John'
    
  4. 构造函数调用: 当函数作为构造函数使用(使用 new 关键字调用)时,this 指向新创建的对象。

    function Person(name) {
        this.name = name;
    }
    
    var person = new Person('Alice');
    console.log(person.name); // 输出 'Alice'
    
  5. 箭头函数: 箭头函数没有自己的 this,它会捕获其所在上下文的 this 值,箭头函数的 this 由包含它的非箭头函数决定。

    var obj = {
        name: 'John',
        sayHello: function() {
            setTimeout(() => {
                console.log(this.name);
            }, 1000);
        }
    };
    
    obj.sayHello(); // 输出 'John'(箭头函数中的 this 指向 obj)
    

需要注意的是,this 的指向是动态确定的,在运行时根据函数的调用方式决定,因此在编写代码时需要注意上下文。

  • 原型和原型链

js原生的方法获取dom元素

JavaScript 原生方法获取 DOM 元素有多种方式,其中一些常用的包括:

  1. document.getElementById(): 这是最常用的方法,通过元素的 ID 属性来获取对应的 DOM 元素。例如:

    var element = document.getElementById('myElement');
    
  2. document.getElementsByClassName(): 这个方法可以获取具有指定类名的所有 DOM 元素的集合。它返回一个类数组对象(HTMLCollection),可以通过索引访问其中的元素。例如:

    var elements = document.getElementsByClassName('myClass');
    
  3. document.getElementsByTagName(): 这个方法可以获取具有指定标签名的所有 DOM 元素的集合。它返回一个类数组对象(HTMLCollection),可以通过索引访问其中的元素。例如:

    var elements = document.getElementsByTagName('div');
    
  4. document.querySelector(): 这个方法可以使用 CSS 选择器语法来获取匹配的第一个 DOM 元素。它返回的是一个 DOM 元素对象,如果没有匹配到任何元素,则返回 null。例如:

    var element = document.querySelector('#myElement');
    
  5. document.querySelectorAll(): 这个方法与 document.querySelector() 类似,但它会返回匹配到的所有 DOM 元素的集合。它返回一个 NodeList 对象,可以通过索引访问其中的元素。例如:

    var elements = document.querySelectorAll('.myClass');
    

以上这些方法都是 JavaScript 原生提供的,可以根据具体需求选择合适的方法来获取 DOM 元素。

getElementById,如果有两个id一样的,返回什么?

在 HTML 中,每个元素的 ID 属性应该是唯一的,即不应该存在两个具有相同 ID 的元素。如果出现了两个 ID 相同的元素,这违反了 HTML 的规范,可能会导致意外的行为。

根据 HTML 的规范,getElementById 方法应该返回匹配到的第一个具有指定 ID 的元素。如果存在两个 ID 相同的元素,getElementById 方法仍然只返回第一个匹配到的元素。这意味着无法准确预测返回的元素是哪一个,因此在编写 HTML 时,应该确保每个元素的 ID 唯一。

事件委托

事件委托(Event Delegation)是一种常用的 JavaScript 编程技巧,用于简化事件处理程序的管理和提高性能。事件委托的原理是将事件处理程序绑定到一个父级元素上,利用事件冒泡的特性,在父级元素上统一处理子级元素的事件。

事件委托的主要步骤如下:

  1. 确定委托目标: 确定一个父级元素作为事件的委托目标,通常选择这些子元素的共同父元素或更高层级的元素作为委托目标。

  2. 绑定事件处理程序: 将事件处理程序绑定到委托目标上。这个事件处理程序通常是一个回调函数,负责处理委托目标下的所有子元素的特定事件。

  3. 事件处理程序内部逻辑: 在事件处理程序内部,通过判断事件的目标(event.target)来确定触发事件的子元素是哪个,并执行相应的逻辑处理。

使用事件委托的优点包括:

  • 减少内存占用: 通过将事件处理程序绑定到父级元素上,而不是每个子元素上,可以减少内存占用,提高性能。
  • 动态元素处理: 对于动态添加的子元素,无需重新绑定事件处理程序,因为事件是在父元素上监听的。
  • 简化管理: 可以通过一个统一的事件处理程序来管理多个子元素的事件,减少了代码量和维护成本。

下面是一个简单的示例代码,演示了如何使用事件委托:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Delegation Example</title>
<style>
  ul { list-style: none; padding: 0; }
  li { cursor: pointer; padding: 5px; margin: 5px; background-color: #f0f0f0; }
  .highlight { background-color: yellow; }
</style>
</head>
<body>
  <ul id="parent-list">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>

<script>
document.getElementById('parent-list').addEventListener('click', function(event) {
  if (event.target.tagName === 'LI') {
    event.target.classList.toggle('highlight');
  }
});
</script>
</body>
</html>

在这个示例中,点击父级 <ul> 元素中的任何一个子元素 <li>,都会切换其高亮样式。事件委托的好处在于无需为每个 <li> 元素分别绑定事件处理程序,只需要将事件处理程序绑定到父级 <ul> 元素上即可。

如何阻止冒泡

阻止事件冒泡(Event Bubbling)是指阻止事件从触发元素向其父级元素传播的过程。在JavaScript中,可以使用以下两种方式来阻止事件冒泡:

  1. stopPropagation() 方法: stopPropagation() 方法是事件对象的一个方法,调用该方法可以阻止事件的进一步传播。当事件触发时,调用事件对象的 stopPropagation() 方法可以阻止事件冒泡到父级元素。

    element.addEventListener('click', function(event) {
        event.stopPropagation();
        // 其他处理逻辑
    });
    
  2. 使用事件捕获阶段: 事件传播过程分为捕获阶段(Capture Phase)和冒泡阶段(Bubbling Phase),可以在事件的捕获阶段阻止事件的进一步传播。通过将事件处理函数绑定到父级元素的捕获阶段,可以在父级元素捕获到事件之后立即阻止事件的进一步传播。

    parentElement.addEventListener('click', function(event) {
        event.stopPropagation();
        // 其他处理逻辑
    }, true); // 第三个参数指定事件绑定在捕获阶段
    

需要注意的是,stopPropagation() 方法只会阻止事件的冒泡传播,而不会影响事件的默认行为。如果需要同时阻止事件的默认行为,可以结合使用 preventDefault() 方法。

element.addEventListener('click', function(event) {
    event.stopPropagation();
    event.preventDefault();
    // 其他处理逻辑
});

综上所述,可以使用 stopPropagation() 方法或在事件的捕获阶段阻止事件的进一步传播来阻止事件冒泡。

webpack了解吗?解析过程

Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它主要用于打包 JavaScript 模块,但也能够打包 CSS、图片、字体等资源。Webpack的解析过程主要包括以下几个步骤:

  1. 识别入口文件: Webpack 会根据配置文件(通常是 webpack.config.js)中的入口配置,找到应用程序的入口文件。入口文件是整个应用程序的起点,Webpack会从入口文件开始分析模块的依赖关系。

  2. 解析模块依赖: Webpack会从入口文件开始递归地解析模块的依赖关系。它会分析模块代码中的 import、require 等语句,找到模块之间的依赖关系,并将依赖关系构建成一个依赖图。

  3. 选择加载器(Loader): 在解析模块代码时,如果遇到非 JavaScript 文件(如 CSS、图片等),Webpack 会根据配置文件中的 Loader 配置选择合适的加载器来处理这些文件。加载器可以对模块进行转换,例如将 ES6 语法转换为 ES5、将 SCSS 文件转换为 CSS 等。

  4. 应用插件(Plugin): 在打包过程中,Webpack 还可以应用各种插件来完成一些额外的任务,例如压缩代码、提取 CSS 文件、拷贝静态文件等。插件可以通过配置文件进行配置,然后在 Webpack 的打包过程中自动运行。

  5. 生成输出文件: 在解析完所有模块的依赖关系后,Webpack 将根据配置文件中的输出配置,将打包后的文件生成到指定的目录中。通常情况下,Webpack 会生成一个或多个 JavaScript 文件作为输出,同时也会生成对应的 CSS 文件、图片文件等资源。

以上是 Webpack 的基本解析过程,它会根据入口文件、模块依赖、加载器和插件等配置信息,将应用程序的所有模块打包成一个或多个输出文件。Webpack 的灵活配置和丰富的生态系统使得它成为了前端开发中最受欢迎的打包工具之一。

如果不使用webpack来实现模块依赖,应该使用什么样的方式来实现模块相互依赖

如果不使用Webpack等构建工具来实现模块依赖,可以考虑使用以下几种方式来实现模块相互依赖:

  1. 原生ES模块: 使用原生的ES模块系统可以在现代浏览器中实现模块化开发。通过在HTML文件中使用

  2. AMD(Asynchronous Module Definition): 使用AMD规范可以实现模块化开发,并且支持在浏览器中异步加载模块。通过使用RequireJS等AMD加载器,可以定义模块和模块之间的依赖关系,并在需要时异步加载依赖模块。AMD规范相对于原生ES模块更灵活,适用于较旧版本的浏览器。

  3. CommonJS: CommonJS是一种在服务器端(如Node.js)广泛使用的模块化规范,可以实现模块化开发和模块之间的依赖管理。通过使用require和module.exports语法,可以定义和导出模块,并在其他模块中使用require来引入依赖模块。CommonJS规范相对于原生ES模块更成熟,但主要适用于服务器端开发。

  4. 手动管理依赖关系: 如果项目规模较小,可以手动管理模块之间的依赖关系。通过在HTML文件中按照依赖关系手动引入JavaScript文件,并确保脚本文件的加载顺序正确,可以实现模块之间的相互依赖。这种方式简单直接,但不适用于大型项目和复杂的依赖关系。

综上所述,可以根据项目需求和开发环境选择合适的方式来实现模块相互依赖。原生ES模块适用于现代浏览器环境,AMD和CommonJS适用于较旧版本的浏览器或服务器端开发,手动管理依赖关系适用于较小规模的项目。

css的盒模型

CSS盒模型(Box Model)是CSS中用来描述元素布局的基本概念。每个HTML元素可以看作是一个矩形的盒子,包含内容区域、内边距、边框和外边距等部分。CSS盒模型将这些部分划分为不同的区域,如下所示:

  1. 内容区域(Content Area): 内容区域是盒子中用于显示内容的部分,它的大小由元素的width和height属性决定。内容区域是盒子的核心部分,显示元素的文本、图像或其他内容。

  2. 内边距(Padding): 内边距是内容区域与边框之间的空白区域,用于控制内容与边框之间的距离。内边距可以使用padding属性来设置,可以分别设置上、右、下、左四个方向的内边距,也可以同时设置所有方向的内边距。

  3. 边框(Border): 边框是围绕内容区域和内边距的线条或样式,用于装饰和显示元素的边界。边框可以使用border属性来设置,可以设置边框的宽度、样式和颜色等属性。

  4. 外边距(Margin): 外边距是盒子与相邻元素之间的空白区域,用于控制元素与其他元素之间的距离。外边距可以使用margin属性来设置,可以分别设置上、右、下、左四个方向的外边距,也可以同时设置所有方向的外边距。

CSS盒模型的标准模型和IE盒模型有所不同。标准模型的width和height属性指的是内容区域的大小,而IE盒模型的width和height属性包括了内容区域、内边距和边框的大小。在实际开发中,可以使用box-sizing属性来指定盒模型的计算方式,可以选择content-box(标准模型)或者border-box(IE模型)。

总的来说,CSS盒模型是描述元素布局的重要概念,通过内容区域、内边距、边框和外边距等部分的组合,可以灵活地控制元素的大小、间距和样式,实现丰富多样的布局效果。

移动端的适配方案

移动端适配是指针对不同尺寸和分辨率的移动设备进行页面布局和样式调整,以确保在不同设备上都能够获得良好的显示效果和用户体验。以下是几种常见的移动端适配方案:

  1. 响应式布局(Responsive Web Design): 响应式布局是一种通过使用CSS3的媒体查询(Media Queries)来适配不同尺寸和分辨率的设备的方法。通过设置不同的CSS样式,使得网页可以根据设备的屏幕尺寸动态调整布局和样式,以适应不同大小的屏幕。

  2. Viewport单位: Viewport单位(如vw、vh等)是相对于视口大小的单位,可以根据设备的视口大小来调整元素的大小和位置。使用Viewport单位可以实现简单的移动端适配,但需要注意兼容性和布局问题。

  3. Flexible Box布局(Flexbox): Flexbox是一种用于布局的CSS3模块,可以方便地创建灵活的、自适应的布局。Flexbox提供了一种强大的方式来实现移动端适配,可以轻松地实现水平和垂直居中、自适应布局等效果。

  4. Rem布局: Rem(Root em)是相对于根元素字体大小的单位,可以根据根元素的字体大小来调整元素的大小。通过设置根元素的字体大小,可以实现简单的移动端适配,但需要注意兼容性和布局问题。

  5. CSS预处理器: 使用CSS预处理器(如Sass、Less等)可以简化样式编写的过程,并且提供了一些方便的工具和函数来实现移动端适配。例如,可以使用Mixin来自动生成适配不同设备的样式,或者使用函数来计算元素的大小和位置。

  6. JavaScript库: 一些JavaScript库(如Bootstrap、Ant Design等)提供了专门针对移动端的样式组件和工具,可以快速实现移动端适配。这些库通常提供了一些常用的响应式布局、栅格系统、移动端样式组件等,可以大大减少开发成本和时间。

综合考虑项目需求、技术栈和团队能力,选择合适的移动端适配方案进行开发。通常情况下,响应式布局、Viewport单位和Flexbox布局是比较常用和灵活的移动端适配方案。

前端性能优化

CDN是什么?如何做性能优化?

CDN(Content Delivery Network,内容分发网络)是一种分布式的网络架构,旨在提高用户对网站、应用或其他互联网内容的访问速度和性能。CDN通过将内容(如网页、图像、视频、应用程序等)缓存到位于全球各地的服务器上,并根据用户的地理位置和网络条件,将用户的请求定向到最近的服务器节点上,从而实现更快速的内容传输和更低的延迟。

CDN的工作原理通常包括以下几个步骤:

  1. 缓存:CDN服务商将网站、应用或其他内容的静态资源(如图片、CSS、JavaScript文件等)缓存到分布式的服务器节点上。
  2. 就近访问:当用户发起访问请求时,CDN会根据用户的地理位置和网络条件,将请求定向到离用户最近的服务器节点上。
  3. 加速传输:CDN服务器节点会快速响应用户的请求,提供高速的内容传输,从而减少了数据传输的延迟和提高了用户的访问速度。

CDN的性能优化通常包括以下几个方面:

  1. 静态资源缓存: 将网站、应用或其他内容的静态资源(如图片、CSS、JavaScript文件等)缓存到CDN服务器节点上,减少了数据传输的延迟和提高了用户的访问速度。
  2. 就近访问: CDN根据用户的地理位置和网络条件,将用户的请求定向到离用户最近的服务器节点上,从而实现更快速的内容传输和更低的延迟。
  3. 动态内容缓存: 一些CDN服务商还支持动态内容的缓存,将动态生成的内容(如网页、API响应等)缓存到CDN服务器节点上,提高了内容的访问速度和性能。
  4. 负载均衡: CDN服务商通常会采用负载均衡技术,将用户的请求分配到多个服务器节点上,避免了单个节点的性能瓶颈,提高了整体的服务稳定性和可靠性。
  5. 安全防护: 一些CDN服务商还提供安全防护功能,包括DDoS攻击防护、Web应用防火墙(WAF)等,保护网站和应用免受恶意攻击。

综上所述,CDN通过缓存、就近访问、动态内容缓存、负载均衡和安全防护等技术手段,实现了对网站、应用或其他内容的性能优化,提高了用户的访问速度和体验。

CDN如何就近分配?是根据什么分配的?

CDN(Content Delivery Network,内容分发网络)通过就近分配来提高用户访问网站的速度和性能。就近分配是指将用户请求的内容服务节点分配到离用户最近的网络节点上,以减少数据传输的延迟和提高访问速度。CDN实现就近分配主要依靠以下几个方面:

  1. 网络拓扑结构: CDN提供商会在全球范围内部署大量的服务器节点,这些节点分布在各个地理位置上。这些服务器节点被布置在不同的网络交换点、数据中心以及云服务提供商等地,以确保覆盖范围广泛并且离用户尽可能近。

  2. IP地址定位: CDN服务商通常会利用IP地址定位技术,根据用户的IP地址确定用户的地理位置。根据用户的地理位置和网络拓扑结构,CDN可以将用户请求分配到距离用户最近的服务器节点上。

  3. DNS解析: CDN服务商会通过DNS解析技术,根据用户的域名解析请求将用户的请求指向最优的服务器节点。当用户访问网站时,DNS服务器会根据用户的地理位置和网络条件选择合适的CDN服务器节点,将用户的请求定向到最近的服务器节点上。

  4. Anycast技术: CDN服务商通常会采用Anycast技术来实现就近分配。Anycast是一种路由技术,它允许多个服务器节点共享相同的IP地址,并且将用户请求路由到距离用户最近的服务器节点上。这样可以更快地响应用户请求,提高访问速度和性能。

总的来说,CDN通过网络拓扑结构、IP地址定位、DNS解析和Anycast技术等手段实现就近分配,将用户的请求分配到离用户最近的服务器节点上,以提高用户访问网站的速度和性能。

懒加载

懒加载(Lazy Loading)是一种延迟加载资源的技术,它的主要目的是提高网页的加载速度和性能。懒加载的原理是在页面初始化时只加载页面上可见区域的内容,而不加载页面上不可见区域的内容,当用户滚动页面到可见区域时再动态加载相应的内容。

懒加载通常应用于以下场景:

  1. 图片懒加载: 当页面包含大量图片时,可以先加载页面上可见区域的图片,而延迟加载页面上不可见区域的图片。当用户滚动页面时,再动态加载进入可见区域的图片,避免了一次性加载大量图片导致页面加载缓慢的问题。

  2. 页面内容懒加载: 对于较长的页面内容,可以将页面分成多个部分,只加载当前可见区域的内容,延迟加载其他部分的内容。当用户滚动页面时,再动态加载进入可见区域的内容,提高了页面的加载速度和用户体验。

  3. 组件懒加载: 在前端框架中,可以将页面的组件按需加载,即只在需要使用组件时才加载对应的代码和资源。这样可以减少页面的初始加载时间,并且根据用户的实际操作情况动态加载组件,提高了页面的性能和响应速度。

懒加载的实现可以通过以下方式:

  • 监听滚动事件: 监听页面滚动事件,当滚动到特定位置时触发加载操作。
  • 使用Intersection Observer API: Intersection Observer API是一种现代的浏览器API,可以异步监视目标元素与其祖先元素或顶级文档视窗交叉状态的变化。可以利用该API实现图片懒加载等效果。
  • 使用第三方库: 有许多第三方JavaScript库和框架提供了懒加载功能的实现,如jQuery LazyLoad、Lozad.js等。

总的来说,懒加载是一种优化网页加载速度和性能的有效方式,可以减少不必要的资源加载,提高用户体验。在开发中,根据实际情况选择合适的懒加载实现方式,并合理应用于页面中,可以有效优化页面的性能。

  • 一般会去什么网站关注新技术发展?

反问:部门技术栈(内心os:已经g了一点也不想反问)

#前端##前端 开发工程师##前端八股##前端面试[话题]##阿里[话题]#