知识架构
html的语义化
其实前端大多数情况下是可以靠div和span就能搭建一个基本的网站,但是语义化也有语义化的意义,
- 更适合机器阅读,如引擎搜索,又如盲人阅读器
- 使结构更明确,即使没有css的情况下,也可以清晰看出网页的结构
很多情况下,我们说话没有唯一的表达方式,语义话标签的使用也是这样,下面是几个使用场景。
- 作为纯文本的补充,用于表达一定的结构或者消除歧义
今天我吃了一个苹果 可以表述为
<em>今天</em>我吃了一个苹果
今天我吃了<em>一个</em>苹果
今天我吃了一个<em>苹果</em>
- 作为标题摘要的语义类标签
<h1>HTML语义</h1>
<p>balah balah balah balah</p>
<h2>弱语义</h2>
<p>balah balah</p>
<h2>结构性元素</h2>
<p>balah balah</p>
当h元素放在section中时,h的层级会下降
<section>
<h1>大标题</h1>
<p>balbalba</p>
<h2>小标题</h2>
<p>balaala</p>
<h2>小标题2</h2>
<p>balabal</p>
</section>
一个典型的body
<body>
<header>
<nav>
……
</nav>
</header>
<aside>
<nav>
……
</nav>
</aside>
<section>……</section>
<section>……</section>
<section>……</section>
<footer>
<address>……</address>
</footer>
</body>
部分标签的意义
- aside -- 导航性质的工具内容(侧边栏)
- nav -- 导航(目录、导航栏、超链接)
- article -- 文章
- abbr -- 缩写
- hr -- 效果为一条横线,意义为故事走向的转变或话题的转变
- strong -- 强调 表现为加粗
- time -- 时间
- figure, figcaption -- 与主文章相关的图像、照片等流内容
- dfn -- 被定义的元素
- pre -- 预定义的内容,不需要浏览器进行排版
- code -- 代码
- small -- 补充评论
- s -- 错误的内容,如打折前的价格,表现为中间的一条横线
- i -- 表示读的时候变调
- b -- 表示关键字
- u -- 表示避免歧义的标注
- data -- 和time类似,只是给机器读的内容
- menu -- ul的变体,用于功能菜单时使用
- main -- 整个页面只出现一个,表示页面的主要内容,可以理解为特殊的div
javascript类型
- undefined -- 未定义
一个变量 而不是关键字 我们可以使用 void 0 来获取undefined值,防止undefined被篡改 - null -- 定义了 但是是空值
- boolean
- string -- 有长度限制的字符串
- number
注意 +0 和 -0相加时没有区别 但是除法时,1/0 = Infinity 1/-0 = -Infinity
小数相加有精度问题 判断可以这么判断,javaScript提供的最小精度值:Number.EPSILON
console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
- symbol -- 一切非字符串的对象key的集合,es6引入的新类型
var mySymbol = Symbol("my symbol");
- object -- 属性的集合
属性分为数据属性和访问器属性,两者都是key-value结构,key可以是字符串或Symbol类型
Number/String/Boolean/Symbol都有自己的创建对象方法,如
new Number(2); --> 对象类型
对象的方法也可以在基本类型上使用 ,如
cosole.log("abc".charAt(0)); //a
当与new搭配时,他们产生对象,当直接调用时,他们表示强制类型转换
但symbol不同,直接new会报错
问题:为什么给对象添加的方法能用在基本类型上?
因为运算符提供了装箱操作,它会根据基础类型构建一个临时对象,使得我们能在基础类型上调用对应对象的方法.
类型转换
最好不要使用 == 比较, 而在显示地类型转换后使用 === 比较,因为试图实现跨类型的比较,它的规则复杂到没人能记住
=== 的比较规则
string to number
parseInt/parseFloat/Number
我们知道 0b --> 二进制 0o --> 八进制 0x -- >十进制,但是一些比较老的浏览器会识别错误,所以转化时应该传入parseInt的第二个参数,指定明确转化进制
装箱转换
每一种基本类型Number、String、Boolean、Symbol在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。
那么Symbol函数无法new出对应的对象,但我们仍可以利用函数的call方法来强迫产生装箱
var symbolObject = (function(){ return this; }).call(Symbol("a"));
console.log(typeof symbolObject); //object
console.log(symbolObject instanceof Symbol); //true
console.log(symbolObject.constructor == Symbol); //true
更好的方法是使用内置的Object函数
var symbolObject = Object((Symbol("a"));
console.log(typeof symbolObject); //object
console.log(symbolObject instanceof Symbol); //true
console.log(symbolObject.constructor == Symbol); //true
每一类装箱对象皆有私有的 Class 属性,这些属性可以用 Object.prototype.toString 获取:
var symbolObject = Object((Symbol("a"));
console.log(Object.prototype.toString.call(symbolObject)); //[object Symbol]
在 JavaScript 中,没有任何方法可以更改私有的 Class 属性,因此Object.prototype.toString 是可以准确识别对象对应的基本类型的方法,它比 instanceof 更加准确。
call操作本身会产生装箱操作,需要配合typeod来区分基本类型和对象类型.
拆箱转换
先拆箱再转换,拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。
number先执行valueOf再执行toString
var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}
o * 2
// valueOf
// toString
// TypeError
string先执行toString再执行valueOf
新版google也是先valueOf再toString
var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}
o + ""
// valueOf
// toString
// TypeError
在 ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为。
var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}
o[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}
console.log(o + "")
// toPrimitive
// hello
事实上,“类型”在 JavaScript 中是一个有争议的概念。一方面,标准中规定了运行时数据类型; 另一方面,JS语言中提供了 typeof 这样的运算,用来返回操作数的类型,但 typeof 的运算结果,与运行时类型的规定有很多不一致的地方。我们可以看下表来对照一下。