大家在准备八股的时候,自然会把重心放在css和js上面,html的内容问的很少,大家也就容易忽视。 上次面试的时候,面试官问我,html、css、js你希望我问你哪两个呢?我当时脑子一抽,天真的以为Html不就是那么几个标签吗?能有啥勒!
我于是骄傲的说:那就问js和html吧!
面试官:哈哈哈大笑,直呼有意思,说他们都是选css和js,有意思有意思,问我是故意的还是不小心的
我:虽然听到这个答案有点慌张,但是我还是骄傲的昂起头颅,是故意的!
结果面试官去除了大部的Html内容,保留了一部分Dom和Bom操作并结合一些使用场景向我提问,那些Api我一点没有记,自然获得一首《凉凉》。于是我痛定思痛,决定好好总结一下HTML,Dom,Bom的内容
BOM
BOM的内容相对比较少,我们先从BOM开始
window对象
BOM(Browser Object Model)即浏览器对象模型。BOM的核心是window 对象,表示浏览器的实例。
var/let/const
因为window 对象被复用为ECMAScript的Global 对象,所以通过 var 声明的所有全局变量和函数都会变成window 对象的属性和方法。
如果在这里使用let 或const 替代var ,则不会把变量添加给全局对象
再次回顾一下块级作用域的相关知识
块级作用域: 红宝书上是这么定义的,块级作用域由最近的一对包含花括号{}
界定的。换句话说,if块,while块,function块,甚至单独的块也是let声明变量的作用域。
所以说,let,const创建了块级作用域并不准确,块级作用域是由{}
界定的。只不过let声明的范围是块作用域
既然全局声明时let 或const不会把变量添加给全局对象,那么变量是存储在哪里呢?
执行上文的创建(新的)创建阶段共发生了三件事:
- this的绑定
- 词法环境——标识符变量映射
- 变量环境
词法环境: LexicalEnvironment
主要由环境记录和对外部环境的引用两部分组成。
环境记录:存储当前环境的变量和函数声明的位置(分为对象式Obejct和声明式Declarative)
对外部环境的引用:可以访问外部的词法作用域,构成作用域链
变量环境:VariableEnvironment
也是一个词法环境,拥有和词法环境一样的属性。
词法环境和变量环境的区别:
前者主要用来存储函数声明和变量let和const
后者主要用来存储变量var
let a = 20; const b = 30; var c; function multilpy(e, f) { var g = 20; return e * f * g; } c = multiply(20, 30) GlobalExectionContext = { Thisbinding: <Global Object>, LexicalEnvironment: { EnvironmentRecord: { Type: 'Object', a: <uninitialized>, b: <uninitialized>, multiply: <func> }, outer: <null> }, VariableEnvironment: { EnvironmentRecord: { Type: 'Object', c: undefined. }, outer: <null> } } FunctionExectionContext = { Thisbinding: <Global Object>, LexicalEnvironment: { EnvironmentRecord: { Type: 'Declarative', Arguments: {0: 20, 1: 30, length: 2} }, outer: <GlobalExectionContext> }, VariableEnvironment: { EnvironmentRecord: { Type: 'Declarative', g: 20 }, outer: <GlobalExectionContext> } }
详细可以了解JavaScript 是如何支持块级作用域的, 大致是var声明的会放在变量环境中,let会放在词法环境中
对话框
警告框(alert)通常用于向用户显示一些他们无法控制的消息,比如报 错。用户唯一的选择就是在看到警告框之后把它关闭。
确认框,通过调用confirm() 来显示。确认框跟警告框 类似,都会向用户显示消息。但不同之处在于,确认框有两个按钮: “Cancel”(取消)和“OK”(确定)。用户通过单击不同的按钮表明希 望接下来执行什么操作。比如,confirm("Are you sure?")
要知道用户单击了OK按钮还是Cancel按钮,可以判断confirm() 方法的 返回值:true 表示单击了OK按钮,false 表示单击了Cancel按钮或者通 过单击某一角上的X图标关闭了确认框。确认框的典型用法如下所示:
if (confirm("Are you sure?")) { alert("I'm so glad you're sure!"); } else { alert("I'm sorry to hear you're not sure."); }
提示框,通过调用prompt() 方法来显示。提示框的用 途是提示用户输入消息。除了OK和Cancel按钮,提示框还会显示一个文本 框,让用户输入内容。prompt() 方法接收两个参数:要显示给用户的文 本,以及文本框的默认值(可以是空字符串)。
如果用户单击了OK按钮,则prompt() 会返回文本框中的值。如果用户单 击了Cancel按钮,或者对话框被关闭,则prompt() 会返回null 。
location 对象
location属性
属性 | 描述 |
hash | 锚点部分,以# 开头 |
host | 主机名 + 端口号 |
hostname | 主机名 如127.0.0.1 localhost 等 |
href | 包含完整URL origin 协议 + 主机名 + 端口号(我们常说的跨域,跨的就是它) |
pathname | 路径部分,以 / 开头 port 端口,常见的80 443 等 |
protocol | URL对应的协议,注意最后是有一个: 的,如http: https: 等 |
search | 参数部分,以? 开头 |
location方法
方法 | 描述 |
assign | 加载新页面 |
reload | 重加载当前页面 |
replace | 用一个新页面代替当前页面 |
reload
方法.此方法的参数是一个可选的布尔类型,不填默认为false
,表示可能从缓存中读取当前页面刷新,相当于普通的F5刷新,true
表示强制浏览器从服务器去重新获取页面资源,相当于强制刷新
URLSearchParams
URLSearchParams 提供了一组标准API方法,通过它们可以检查和修改 查询字符串。给URLSearchParams 构造函数传入一个查询字符串,就可 以创建一个实例。这个实例上暴露了get() 、set() 和delete() 等方 法,可以对查询字符串执行相应操作。
let qs = "?q=javascript&num=10"; let searchParams = new URLSearchParams(qs); alert(searchParams.toString()); // " q=javascript&num=10" searchParams.has("num"); // true searchParams.get("num"); // 10 searchParams.set("page", "3"); alert(searchParams.toString()); // " q=javascript&num=10&page=3" searchParams.delete("q"); alert(searchParams.toString()); // " num=10&page=3"
大多数支持URLSearchParams 的浏览器也支持将URLSearchParams 的实例用作可迭代对象:
let qs = "?q=javascript&num=10"; let searchParams = new URLSearchParams(qs); for (let param of searchParams) { console.log(param); } // ["q", "javascript"] // ["num", "10"]
history对象
出于安全考虑,history对象不会暴露用户访问过的URL,但是可以在它不知道实际的URL情况下完成前进和后退
history对象中有一个go方法,它可以控制浏览器的前进后退,它的参数为一个数字,代表的时浏览器前进或者后退多少步。
示例代码:
// 后退一页 history.go(-1) history.back() // 前进一页 history.go(1) history.forward() // 前进两页 history.go(2)
pushState()
在以前,我们每次变化url是则代表重新刷新页面,比如浏览器前进后退则代表刷新整个页面,这种用户体验是非常查的.
为了解决这类问题, 出现了hashChange事件,它会在页面url的Hash变化时被触发, 这个时候我们可以执行一些我们自己的操作。
而我们的history对象中有一个pushState方法, 该方法可以让开发者改变浏览器URL的时候不会加载新的页面. 该方法接收三个参数.
- 第一个参数:stateObj, 当popState事件触发时,会将其作为第一个参数传入到popState事件的函数中,大小限制在500kB - 1MB之间
- 第二个参数:一个新状态的标题字符串,也可以为空 (目前被忽略)
- 第三个参数:一个(可选的)相对URL
history.pushState(stateObject, "My title", "baz.html");
pushState的具体使用方法和规则可以参考:
MDN:pushState
[高级]深入浅出浏览器的history对象 - 掘金 (juejin.cn)
replaceState()
history.replaceState()
的使用与 history.pushState()
非常相似,区别在于 replaceState()
是修改了当前的历史记录项而不是新建一个。注意这并不会阻止其在全局浏览器历史记录中创建一个新的历史记录项。
popState()
当我们pushState或者replaceState后,浏览器不会刷新也不会加载对应的文件。当我们回退访问历史记录时,会触发popState()
DOM
文档对象模型(DOM,Document Object Model)是HTML和XML文档的编程接口。
Node、ELement 和 HTMLElement 有什么关系?
几种获取dom元素的方法
- getElementById() 返回匹配指定选择器的第一个元素(获取不到为 null)
- querySelector()
- getElementsByClassName 返回匹配指定选择器的第一个元素(获取不到为null)
- querySelectorAll()
- getElementsByTagName
- getElementsByName
总结:
(1)所有获取DOM对象的方法中,只有getElementById()和querySelector()这两个方法直接返 回的DOM对象本身,可直接为其绑定事件。
(2)getElementXXX类型的方法,除了通过Id获取元素,其他都返回一个集合,如果需要取到具体 的DOM元素,需要加索引,如:document.getElementsByClassName(“div”)[0] =>获取class为 box的所有元素中的第一个DOM元素。
获取dom元素的节点get和query区别
- getElementsByClassName、getElementsByTagName得到的是html引用对象(HTMLCollection),不能使用forEach函数遍历。 getElementsByName、querySelectorAll得到的是NodeList,可以使用forEach函数遍历。
- querySelectorAll获取到的数组是静态的。【box2.length】不会随着元素创建动态增长
- getElementsByName、getElementsByClassName和getElementsByTagName获取到的数组是动态的。
HTML
H5新特性
- 语义化标签 (header, nav, footer, aside, article, section)
- 音频、视频 (audio(MP3, Wav, Ogg), video(MP4, WebM, Ogg))
- 画布 (Canvas)
- 本地存储 (LocalStorage, sessionStorage)
- 表单控件 (calendar, datetime, date, time, email, url, search, number, color, month, week)
- 新技术 (webworker, websocket, Geolocation)
行内和块级元素
块级元素
常见块级元素:<h1> - <h6> <p> <div> <ul> <li>
H5: <header> <footer> <main> <aside> <section>
注意
- 文字类元素不能使用块级元素
- 标签用来存放文字,因此不能放块级元素
- 同理
<h1> - <h6>
都是文字类块级标签,不能放其他块级元素
行内元素
常见行内元素: <a> <strong> <span> <input> <textarea> <small> <progress>
注意
- 高宽直接设置无效
- 默认是它本身内容的宽度
- 行内元素只能容纳文本或者其他行内元素
- 链接里面不能再放链接
<a>
里面可以放块级元素
结尾
欢迎大家评论区补充你遇到的有意思的Html, DOM, BOM面试题,我也会进一步整理
都看到这里了,那就点个赞再走吧!