1 语义类标签(CSS部分)
1.1 定义
如section
、nav
、p
,div
,span
,特点是视觉表现上互相都差不多,主要区别在于表达语义的不同。
1.2 正确使用语义标签的好处
1、增强了可读性,HTML最初的设计场景就是“超文本”;
2、适宜机器阅读,搜索引擎爬虫更好地获取到更多有效信息;
3、正确应用语义化结构能让浏览器很好地支持“阅读视图功能”,还可以让搜索引擎的命中率提升,同时,它也对视障用户的读屏软件更友好。
1.2 语义类标签的一些使用
1、hgroup
和h1
-h6
的作用,hgroup
是标题组,h1
是一级标题,h2
是二级标题;
2、aside
是导航性质的内容;
3、article
,文章主体部分;
4、abbr
标签表示缩写;
5、hr
表示故事走向的转变或者话题的转变,一般的横线使用CSS的border
来表示;
6、strong
表示黑体,em
表示重音;
7、blockquote
表示段落级引述内容,q
表示行内的引述内容,cite
表示引述的作品名;
2 JavaScript数据类型
2.1 定义
JavaScript语言中的每个值都属于一种数据类型,一共有7种数据类型,广泛用于变量、函数参数、表达式、函数返回值等场合;
数据类型可以分为原始类型以及引用类型(也称对象类型)。
原始类型与引用类型的差异:
var a = 'hello world';
var b = a;
var a = 'hello javascript';
console.log(a); //hello javascript
console.log(b); //hello world
var obj1 = {
name: 'jack',
age: 18
}
var obj2 = obj1;
obj1.name = 'rose';
console.log(obj1.name); //rose
console.log(obj2.name); //rose
原始类型(对象类型):
2.2 Undefined、Null
Undefined
类型表示未定义,值为undefined
;任何变量在赋值前都是Undefined
类型;又因为JavaScript的代码undefined
是一个变量,为了避免无意中被篡改,一般我们用void 0
(void
运算符对给定的表达式进行求值,因为是0
所以返回undefined
)代替undefined
,用void 0
代替undefined
还可以节省3个字节。
Null
类型表示“定义了但是为空”,值为null
;Null
与Undefined
的区别:undefined
是访问一个未初始化的变量时返回的值,而null
是访问一个尚未存在的对象时所返回的值,可以把undefined
看作是空的变量,而null
看作是空的对象。
2.3 Boolean
Boolean
类型有两个值, true
和false
。
2.4 String
String
类型用于表示文本数据,String
类型有最大长度是 2^53 - 1,这个最大长度是受字符串的编码长度影响的,所以String
类型的意义并非“字符串”,而是字符串的 UTF16 编码,我们字符串的操作charAt
、charCodeAt
、length
等方法针对的都是 UTF16 编码。
2.5 Number
Number
类型表示我们通常意义上的“数字”这个数字大致对应数学中的有理数,有一定的精度限制;Number
类型在基本符合 IEEE754-2008 规定的双精度浮点数规则的情况下,还引入了Infinity
(无穷大)和-Infinity
(负无穷大)。
值得注意的是,JavaScript中有+0
和-0
(0
和负数进行运算时,我们就可以得到-0
),我们对1
分别除以+0
和-0
时会得到Infinity
和-Infinity
,并且它们并不相等,但是在将+0
和-0
做字符串转换时我们会得到一样的结果,===
比较的结果也为true
;+0
与-0
的使用——我们有时会用符号位存储一些信息,比较向量或速度的方向信息,如速度-0
,负号代表着运动的方向,保留了负号位可以防止这些信息的丢失。
为什么0.1+0.2
不能=0.3
?因为这是使用基于IEEE754数值的浮点计算的通病,不能精确表示0.1
,0.2
这样的浮点数,使用这种数值格式的语言计算时使用的是带有舍入误差的数(当代码被编译或解释后,0.1
会被四舍五入成一个与之很接近的数字),但也不是所有的浮点数都存在舍入误差,比如0.5
就没有舍入误差;我们尽量不要直接比较两个浮点的大小,如果真有需要的话,使用JavaScript提供的最小精度值(检查等式左右两边差的绝对值是否小于最小精度):
console.log( 0.1 + 0.2 == 0.3); // false
console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON); // true
2.6 Symbol
Symbol
是 ES6 中引入的新类型,表示独一无二的值,它是一切非字符串的对象key
(对应value
)的集合,这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol
类型;还有,每个Symbol
实例都是唯一的,所以当你比较两个Symbol
实例的时候,将总会返回false
;一些使用场景(简书一斤代码先生)。
注意,Symbol
函数前不能使用new
命令,否则会报错。这是因为生成的Symbol
是一个原始类型的值,不是对象。也就是说,由于Symbol
值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol
的迭代器(Iterator
)应用:
var o = new Object;
o[Symbol.iterator] = function() {
var v = 0;
return {
next: function() {
return { value: v++, done: v > 10 }
}
}
};
for(var v of o);
console.log(v); // 0 1 2 3 ... 9
代码中我们在定义了iterator
之后,用for(var v of o)
就可以调用这个函数,然后我们可以根据函数的行为,产生一个for
…of
的行为。
引用类型:
2.7 Object
在 JavaScript 中,对象类型的定义是“属性的集合”。对象类型的属性分为数据属性和访问器属性(在第④章详细解析)两种,二者都是key
-value
(键值对形式存储属性)结构,key
可以是字符串或者 Symbol
类型。
JavaScript中的几个原始类型,都在对象类型中有一个“亲戚”。它们是Number
、String
、Boolean
和Symbol
;
如string
类型(var a = 'abc';
)和string
对象(var a = new String('abc');
),3
和 new Number(3)
,它们其实是不一样的东西(===
不成立);JavaScript 中的对象比较(===
)和 Java 中是一样的,只有引用地址相同才相等。当比较两个引用值时,比较的是两个引用地址,看它们引用的原值是否为同一个副本,而不是比较它们的原值字节是否相等。只有string
、 number
、boolean
这些原始类型才是可以直接对值进行比较。
Number
、String
和Boolean
,三个对象类型(函数构造器)是两用的,当跟new
搭配时,它们产生对象,当直接调用时,它们表示强制类型转换;Symbol
函数比较特殊,直接用new
调用它会抛出错误,但它仍然是 Symbol
对象的构造器。
2.8 类型转换 ★
大部分运算都会涉及类型转换。其中的 ==
运算,如果类型不一样,总是试图去做类型转化,里面的规则非常复杂,很容易造成一些代码中的判断失误,所以不推荐直接使用==
运算,推荐进行显式的类型转换后,再用===
比较;而其它运算,如加减乘除大于小于,也都会涉及类型转换,所幸的是,实际上大部分类型转换规则比较简单,较为复杂的部分是Number
和String
之间的转换,以及对象跟原始类型之间的转换,如下表所示:
2.8.1 StringToNumber
字符串到数字的类型转换,有三种方法:Number()
、parseInt()
、parseFloat()
;类型转换支持十进制(30)、二进制(0b111)、八进制(0o13)、十六进制(0xFF)、正负号科学计数法(1e3或-1e-2),其中Number()
可以用于任何数据类型转换成数值,parseInt()
处理整数时更常用,parseFloat()
专门用于把字符串转换成数值。
parseInt()
在不传入第二个参数的情况下,只支持16进制前缀 “0x” ,而且会忽略非数字字符,也不支持科学计数法,所以建议使用时传入parseInt()
的第二个参数(如:parseInt("10",16)
//按十六进制解析;parseInt("10",8)
//按八进制解析);parseFloat()
则直接把原字符串作为十进制来解析,它不会引入任何的其他进制,一些例子如下:
var num1 = Number("Hello World"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
var num1 = parseInt("He was 40"); //NaN
var num2 = parseInt("40 years"); //40
var num3 = parseInt("34 45 66"); //34
var num4 = parseInt("10", 10); //10
var num5 = parseInt("10", 8); //8
var num6 = parseInt("10"); //10
var num7 = parseInt("010"); //10
var num1 = parseFloat("1234blue"); //1234
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("0908.5"); //908.5
var num4 = parseFloat("3.125e7"); //31250000
总的来讲,Number()
比parseInt()
和parseFloat()
更常用。
2.8.2 装箱转换与拆箱转换(对象类型)
2.8.2.1 拆箱转换
定义:把对象类型转换为原始类型称为拆箱。
方法:toPrimitive(input,preferedType)
,该方法有两个参数,input(输入对象) 和 preferedType
(String
或者Number
,默认为Number
);在preferedType
为默认的情况下,如果 input 输入的是对象或者String
类型,则会尝试调用valueOf
,如果是原始值则直接返回,不是则使用 toString
(如果不是原始值,调用input.toString()
方法,如果是原始值直接返回)来获得拆箱后的原始类型。如果valueOf
和toString
都不存在(方法被覆盖),或者没有返回原始类型,则会产生类型错误;如果 preferedType
值为String
,而且输入的是String
类型,会优先调用toString
,再到valueOf
;
在 ES6 之后,还允许对象通过显式指定@@toPrimitive Symbol
来覆盖方法原有的行为(valueOf
和toString
)。
o[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}
2.8.2.1 装箱转换
定义:把原始类型转换为对应的对象类型的操作称为装箱。
原理:每一种原始类型Number
、String
、Boolean
在对象中都有相应的类。
方法:.toString()
方法;例如
1 .toString() => '1';
注意1
后面有个空格,无则报错;调用过程把1
进行装箱操作转换成Number()
的临时对象。
2.8.2.3 typeof运算
typeof
方法的运算结果和运行时(runtime
)所表示出的类型:
总结如下:
1、typeof
不能区分对象、数组、正则,对它们操作都返回object
;
2、String
/Number
/Boolean
/Undefined
/Object
/function
返回的字符串形式分别为:string
/number
/boolean
/undefined
/object
/function
;
3、特殊情况:
typeof 1/0; // NaN(这个NaN不是字符串类型,是数值类型)
typeof typeof 1/0; // NaN(这个NaN不是字符串类型,是数值类型)
typeof (1/0); // " number"
typeof typeof (1/0); // " string"
typeof (typeof1/0); // " number"