1.说说前端中的事件流
HTML 与 JS 的交互是通过事件驱动来实现的,事件流描述的是JS从页面中接收事件的顺序
事件流包括事件捕获阶段->处于目标阶段->事件冒泡阶段
addEventListener事件柄最后的参数,如果是true,程序就在捕获阶段执行 , 如果是false,程序就在冒泡阶段执行
IE浏览器只支持事件冒泡。
2.事件委托
把事件设置在父元素身上,通过事件冒泡,实现父元素监听子元素的事件
- 减少事件处理的数量:你只需在父元素上绑定一个事件处理程序,就可以管理该父元素下所有子元素的事件。
- 增加程序的灵活性:当新的子元素被添加到父元素中时,它们会自动继承来自父元素的事件处理程序,无需再次手动绑定事件。
事件模型
一、定义
事件模型是一种设计模式。它允许对象之间通过事件进行通信和处理
二、组成部分
- 事件源(Event Source):它是事件的起始点,负责生成并触发事件。
- 事件对象(Event Object):包含事件信息的对象,事件发生时会被传递给事件监听器。
- 事件监听器(Event Listener):负责监听事件,在事件发生时执行处理函数。
三、类型
在Web开发中,DOM事件模型是处理用户交互的主要机制。它分为DOM0级事件、DOM2级事件和IE事件。
- DOM0级事件通过为元素添加事件处理属性(如
onclick
)来实现; - DOM2级事件则通过
addEventListener()
方法来实现,支持为元素添加多个事件监听器并控制事件处理的时机(捕获或冒泡阶段); - IE事件模型通过
attachEvent()
方法实现,但仅支持IE浏览器。
3.JS⾃定义事件
在JavaScript中,自定义事件允许创建并触发自己的事件,然后监听这些事件来执行特定的代码。
1. 创建自定义事件
你可以使用CustomEvent
构造函数来创建一个自定义事件。CustomEvent
构造函数接受几个参数,包括事件名称(type
)、一个配置对象(可选,用于设置事件是否可冒泡、是否可取消等)。
const myEvent = new CustomEvent('myCustomEvent', {
bubbles: true, // 是否冒泡
cancelable: true, // 是否可以取消
detail: { // 传递给事件处理程序的额外数据
message: 'Hello, this is a custom event!'
}
});
2. 监听自定义事件
使用addEventListener
方法可以为元素或对象添加事件监听器,以监听自定义事件。
document.addEventListener('myCustomEvent', function(e) {
console.log(e.detail.message); // 输出: Hello, this is a custom event!
});
3. 触发自定义事件
使用dispatchEvent
方法在元素或对象上触发自定义事件。
// 在document上触发
document.dispatchEvent(myEvent);
// 或者在特定元素上触发
myElement.dispatchEvent(myEvent);
注意事项
- 自定义事件名称不应与现有的DOM事件名称冲突。
- 使用
bubbles
和cancelable
选项可以控制事件的冒泡和取消行为。 detail
属性是传递给事件处理函数的额外数据,它应该是一个对象,这样可以传递更复杂的数据。- 在移除事件监听器时,请确保使用与添加时相同的函数引用(除非使用
removeEventListener
的捕获阶段变体)。
4.addEventListener()和attachEvent()的区别
addEventListener()和attachEvent()都是JavaScript中用于绑定事件处理程序的方法,但它们之间存在几个关键的区别。以下是这些区别的详细分析:
1. 兼容性
- addEventListener():是W3C标准的事件监听方法,在现代浏览器中得到广泛的支持
- attachEvent():主要用于旧版本的IE浏览器(如IE7和IE8)
2. 方法名和参数
- addEventListener():接受三个参数。第一个参数是事件类型(不含"on"前缀,如"click"),第二个参数是事件处理函数,第三个参数用于指定事件在捕获阶段或者冒泡阶段执行
- attachEvent():接受两个参数。第一个参数是事件类型(含"on"前缀,如"onclick"),第二个参数是当事件发生时调用的函数。在IE浏览器中,默认不支持事件冒泡
3. this的指向
- addEventListener():在事件处理函数中,
this
关键字指向触发事件的元素。 - attachEvent():在事件处理函数中,
this
关键字指向window
对象。因为在attachEvent方法中,事件处理程序是在全局作用域下执行的。
4. 事件的执行顺序
- addEventListener():绑定的事件处理程序会按照它们被添加的顺序执行。
- attachEvent():绑定的事件处理程序会按照它们被添加的相反顺序执行,这是IE浏览器特有的行为。
5. 移除事件监听器
- addEventListener():使用
removeEventListener()
方法来移除之前添加的事件监听器。 - attachEvent():使用
detachEvent()
方法来移除之前添加的事件监听器。
5.mouseover 和 mouseenter 的区别
mouseover:当鼠标移入元素或其子元素都会触发事件,有冒泡的过程。对应的移除事件是 mouseout
mouseenter:当鼠标移入元素本身会触发事件,不会冒泡,对应的移除事件是 mouseleave
6.什么是事件监听
事件监听的作用是监听事件的触发, 是事件模型的组成部分
事件模型有三部分
- 事件源(Event Source):触发事件的对象。
- 事件对象(Event):记录事件的相关信息
- 事件监听器(Event Listener):监听事件的触发,并触发处理函数
7.谈谈你对ES6的理解
ES6也称为ECMAScript 2015,是JavaScript语言的一个重大更新版本
ES6的主要新特性
- 变量声明
-
- let:具有块级作用域,不允许在同一作用域内重复声明同一个变量。
- const:也具有块级作用域,声明时必须进行初始化赋值,且赋值后不能再重新赋值修改其值(但如果是一个对象或数组,可以修改其内部属性或元素)。
- 箭头函数
-
- 提供了更简洁的函数写法,并且不创建自己的
this
上下文,继承外层函数的this
值,避免了this
指向错误的问题。
- 提供了更简洁的函数写法,并且不创建自己的
- 模板字符串
-
- 使用反引号(``)标识,支持多行字符串和动态内容插入,使字符串的拼接和处理更加方便、灵活和易读。
- 解构赋值
-
- 允许从数组或对象中提取值,并将其赋给变量,提高了代码的可读性和便捷性。
- 扩展运算符
-
- 主要用于展开数组或对象,以及函数参数传递等场景,提供了更灵活的操作方式。
- 剩余参数
-
- 允许将不定数量的参数表示为一个数组,便于处理函数中的可变参数。
- 模块化
-
- ES6引入了模块化系统,允许开发者将大型代码库分解为更小、更独立的模块,提高了代码的可维护性和复用性。
- 新数据结构
-
- 引入了
Map
和Set
等新的数据结构,提供了更高效的遍历和查找功能。
- 引入了
- 异步编程
-
- 支持
Promise
和async/await
等异步编程特性,提高了异步编程的效率和可读性。
- 支持
ES6的应用与影响
- 前端开发:ES6的新特性极大地提升了前端开发的效率和体验,使得开发者能够编写更加简洁、易读和高效的代码。
- 生态系统:ES6的发布促进了JavaScript生态系统的快速发展,涌现出大量基于ES6特性的工具和库,如Babel等转译器、Webpack等模块打包器等。
8.箭头函数的特性
1. 简洁的语法
- 使用
=>
表示函数定义:箭头函数使用=>
符号来定义,这使得代码更加简洁。
2. 不绑定自己的this
- 继承外层函数的
this
:箭头函数不创建自己的this
值,它会捕获其所在上下文的this
值。 - 无法改变
this
指向:由于箭头函数的this
是词法上确定的,因此call()
、apply()
和bind()
方法无法更改箭头函数内部this
的指向。
3. 不拥有arguments
对象
- 箭头函数没有自己的
arguments
对象。如果需要访问所有参数,使用剩余参数(...args
)。
4. 不具有prototype
属性
- 不是构造函数:箭头函数没有
prototype
属性,因为它们不是构造函数。因此,不能使用new
关键字来调用箭头函数。
7. 注意事项
- 返回对象字面量:如果箭头函数需要返回一个对象字面量,则必须将该对象字面量包裹在括号中,否则会被解释为函数体的一部分。
- 多重箭头函数:多重箭头函数(即箭头函数内部再嵌套箭头函数)可以形成高阶函数,但需要注意作用域和
this
的绑定。
示例
// 简洁的语法
const add = (a, b) => a + b;
// 不绑定自己的this
const person = {
name: 'Alice',
greet: () => console.log(this.name), // 注意:这里的this指向全局对象,而不是person对象
greetWithArrow: function() {
return () => console.log(this.name); // 这里的this指向person对象
}
};
person.greet(); // 可能输出undefined,取决于全局环境
person.greetWithArrow()(); // 输出Alice
// 不拥有arguments对象
const sum = (...args) => args.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3)); // 输出6
// 不具有prototype属性
const func = () => {};
console.log(func.prototype); // undefined
// 返回对象字面量
const getPerson = () => ({ name: 'Bob' });
console.log(getPerson()); // 输出{ name: 'Bob' }
9.对原⽣Javascript了解程度
- 基础语法:
-
- 变量声明(
var
,let
,const
)及其作用域(块级作用域与函数作用域)。 - 数据类型(原始类型如
string
,number
,boolean
,null
,undefined
,symbol
(ES6新增),以及复杂类型如Object
,Array
,Function
)。 - 运算符(算术运算符、比较运算符、逻辑运算符、位运算符等)。
- 条件语句(
if...else
,switch
)和循环语句(for
,while
,do...while
)。
- 变量声明(
- 函数与闭包:
-
- 函数声明与函数表达式。
- 高阶函数、回调函数和匿名函数。
- 闭包的概念及其用途(如封装私有变量)。
this
关键字的作用及其在不同场景下的绑定规则(默认绑定、隐式绑定、显式绑定、new绑定)。
- 对象与原型链:
-
- 对象的字面量语法和构造函数创建对象。
- 原型(
__proto__
)和原型链的概念,以及如何通过原型实现继承。 Object.prototype
上的方法(如hasOwnProperty
,toString
,valueOf
等)。- ES6中引入的
class
关键字和类继承。
- 数组与集合:
-
- 数组的常用方法(如
push
,pop
,shift
,unshift
,slice
,splice
,map
,filter
,reduce
等)。 - 数组迭代方法(
forEach
,for...of
循环)。 - 集合类型(如
Set
,Map
及其迭代器)。
- 数组的常用方法(如
- 异步编程:
-
- 回调函数的使用及其缺点(如回调地狱)。
- Promise对象及其链式调用。
- async/await语法糖,使得异步代码看起来更像是同步代码。
- DOM与BOM操作:
-
- DOM(文档对象模型)的基本操作(如获取元素、修改元素内容、添加/删除事件监听器等)。
- BOM(浏览器对象模型)的基本操作(如操作窗口、定时器、导航和定位等)。
- 了解并应用AJAX(Asynchronous JavaScript and XML)进行异步数据交换。
- ES6+新特性:
-
- 模板字符串、默认参数、展开语法(
...
)、箭头函数等语法糖。 - 模块系统(ES6 Modules)。
Symbol
类型、Set
和Map
集合、Proxy
和Reflect
API等。Promise
、async/await
等异步解决方案。class
语法和类的继承。
- 模板字符串、默认参数、展开语法(
- 性能优化与安全:
-
- 了解JavaScript执行机制(如事件循环、任务队列、宏任务与微任务)。
- 掌握性能优化的技巧(如减少DOM操作、使用事件委托、优化图片和资源加载等)。
- 了解并避免常见的安全漏洞(如XSS攻击、CSRF攻击)。
10.attribute和property的区别是什么
- attribute 是 dom 元素在HTML中 作为标签拥有的属性;
- property 是 dom 元素在JS中 作为对象拥有的属性。
- 在默认情况下,Attribute和Property的值是同步的。
- 但是,一旦用户通过界面交互(如输入文本)改变了元素的状态,Property的值会更新,而Attribute的值则不会(除非通过代码显式更新)。
11.eval是做什么的
- 用法:eval函数接受一个字符串作为参数。如果字符串是表达式,eval会计算并返回表达式的值;如果字符串表示的是语句,eval会执行这些语句。
- 示例:
eval("2 + 3")
会返回5
。 - 安全性:eval可以执行任意代码,应避免在生产环境中使用eval来执行不可信的代码。
12.window.onload和$(document).ready
window.onload: 页面所有元素加载完成后执行
window.onload = function() {
// 页面加载完成后执行的代码
};
// 或者使用 addEventListener(可以添加多个监听器)
window.addEventListener('load', function() {
// 页面加载完成后执行的代码
});
$(document).ready: DOM渲染完成后执行
$(document).ready(function() {
// DOM加载完成后执行的代码
});
// 或者使用更简洁的写法
$(function() {
// DOM加载完成后执行的代码
});