全局对象 window
ECMAScript 规定全局对象叫做 global,但是浏览器把 window 作为全局对象(浏览器先存在的)
window 就是一个哈希表,有很多属性。
window 的属性就是全局变量。
使用window的属性可以不加window.
,
比如window.alert('警告')
可以写成alert('警告')
这些全局变量分为两种:一种是 ECMAScript 规定的
- global.parseInt
- global.parseFloat
- global.Number
- global.String
- global.Boolean
- global.Object
一种是浏览器自己加的属性
- window.alert
- window.prompt
- window.comfirm
- window.console.log
- window.console.dir
- window.document
// document由浏览器实现,但是也有一个自己的标准,那就是 DOM,它的标准由 W3C 制定 - window.document.createElement
- window.document.getElementById
所有 API 都可以在 MDN 里找到详细的资料。
全局函数&简单类型与对象的区别
1. Number()
- MDN
- 阮一峰
Number('1') // 1 强制转换
var n = new Number(1) // 返回一个值为1的对象
在这里,Number()对象作为构造函数使用,用来生成值为数值的对象。和直接赋值数字也就是简单类型的区别:
- 一个是简单类型,一个是复杂类型
- 两者对内存的使用不同,假设有
var n1 = 1
var n2 = new Number(1)
内存图: - 包装对象有许多便捷的操作
- 你可以通过
valueOf()
来获得n2
的原始值1
其它还有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39toString() // 获得字符串形式
toFixed() // 转为指定位数的小数,返回这个小数对应的字符串
toExponential() // 将一个数转为科学计数法形式
toPrecision() // 将一个数转为指定位数的有效数字
(10).toString() // "10"
// toString方法可以接受一个参数,表示输出的进制。如果省略这个参数,默认将数值先转为十进制,再输出字符串;否则,就根据参数指定的进制,将一个数字转化成某个进制的字符串。
(10).toString(2) // "1010"
(10).toString(8) // "12"
(10).toString(16) // "a"
// 上面代码中,之所以要把10放在括号里,是为了表明10是一个单独的数值,后面的点表示调用对象属性。如果不加括号,这个点会被JavaScript引擎解释成小数点,从而报错。
// 只要能够让JavaScript引擎不混淆小数点和对象的点运算符,各种写法都能用。除了为10加上括号,还可以在10后面加两个点,JavaScript会把第一个点理解成小数点(即10.0),把第二个点理解成调用对象属性,从而得到正确结果。
10..toString(2) // "1010"
// 其他方法还包括
10 .toString(2) // "1010"
10.0.toString(2) // "1010"
// toFixed方法用于将一个数转为指定位数的小数,返回这个小数对应的字符串。
(10).toFixed(2) // "10.00"
10.005.toFixed(2) // "10.01"
// toExponential方法的参数表示小数点后有效数字的位数,范围为0到20,超出这个范围,会抛出一个RangeError。
(10).toExponential() // "1e+1"
(10).toExponential(1) // "1.0e+1"
(10).toExponential(2) // "1.00e+1"
(1234).toExponential() // "1.234e+3"
(1234).toExponential(1) // "1.2e+3"
(1234).toExponential(2) // "1.23e+3"
// toPrecision方法的参数为有效数字的位数,范围是1到21,超出这个范围会抛出RangeError错误。
(12.34).toPrecision(1) // "1e+1"
(12.34).toPrecision(2) // "12"
(12.34).toPrecision(3) // "12.3"
(12.34).toPrecision(4) // "12.34"
(12.34).toPrecision(5) // "12.340"两种赋值方式的历史:
var n = new Number(1)
是当初被要求要像java才做出来的方式,实际上更受人喜欢的依然是var n = 1
,
但是这样方式无法使用Number对象的方法怎么办,于是又有了下面的东西;基本包装类型
理论上基本类型是不能没有toString()
之类的方法的,然而实际上却可以使用,
这是因为每当地区一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据,如下:1
2
3
4
5
6
7
8var n = 1 // 1
var s = n.toString() // '1'
// 后台自动操作
var temp = new Number(n) // 创建一个 Number 类型的实例
temp.toString() // 调用指定方法
// 然后将temp.toString()的值作为n.toString()的值
// 最后销毁temp,释放空间
// 所以这是一种临时的转换,基本类型实际上并没有属性,也因此,
var n = new Number(1)
这种方式基本不再被大家所使用思考题
1
2
3
4
5
6var n = 1
n.xxx = 2
// 问:是否会报错?
// NO!
n.xxx = 2 // 2
n.xxx // undefined解析:n.xxx = 2这段代码执行时新建了一个临时变量temp以及属性xxx储存值2,所以不会报错,
但是执行 n.xxx 的时候浏览器显示的却是 undefined,这是因为 temp 是临时创建出来了,使用后会立即销毁,执行 n.xxx 的时候上一句代码创建的临时temp已经被销毁了,这时候又是一个新的temp,它并没有xxx这个属性以及值- String()和Boolean()也是同理
- 阮一峰
- JavaScript高级程序设计第五章-5.6-基本包装类型
2. String()
- MDN
- MDN学习教程
- 阮一峰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45var s = 'abc'
var s2 = new String(s)
// charAt方法返回指定位置的字符,参数是从0开始编号的位置。
s.charAt(1) // "b"
s.charAt(s.length - 1) // "c"
// 这个方法完全可以用数组下标替代。
'abc'.charAt(1) // "b"
'abc'[1] // "b"
// 如果参数为负数,或大于等于字符串的长度,charAt返回空字符串。
'abc'.charAt(-1) // ""
'abc'.charAt(3) // ""
// charCodeAt方法返回给定位置字符的Unicode码点(十进制表示),相当于String.fromCharCode()的逆操作。
'abc'.charCodeAt(1) // 98
// 如果没有任何参数,charCodeAt返回首字符的Unicode码点。
'abc'.charCodeAt() // 97
// 如何返回 16 进制表示的Unicode码点
'abc'.charCodeAt(0).toString(16)
// trim方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。
' hello world '.trim() // "hello world"
// 该方法去除的不仅是空格,还包括制表符(\t、\v)、换行符(\n)和回车符(\r)。
'\r\nabc \t'.trim() // 'abc'
// concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串。
var s1 = 'abc';
var s2 = 'def';
s1.concat(s2) // "abcdef"
s1 // "abc"
s2 // "def"
// 该方法可以接受多个参数。
'a'.concat('b', 'c') // "abc"
// slice方法用于从原字符串取出子字符串并返回,不改变原字符串。
// 它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。
'JavaScript'.slice(0, 4) // "Java"
// 如果省略第二个参数,则表示子字符串一直到原字符串结束。
'JavaScript'.slice(4) // "Script"
// 如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。
'JavaScript'.slice(-6) // "Script"
'JavaScript'.slice(0, -6) // "Java"
'JavaScript'.slice(-2, -1) // "p"
// 如果第一个参数大于第二个参数,slice方法返回一个空字符串。
'JavaScript'.slice(2, 1) // ""String()有很多api,这里只写了几个常用的,更多详见上面两个链接
3. Boolean()
- MDN
- 阮一峰
1
2
3
4
5
6
7
8
9
10
11
12var b = new Boolean(true)
b.toString() // 'true'
b.valueOf() // true
// 踩坑
var f = false
var f2 = new Boolean(false)
if(f) { console.log(1) }
if(f2) { console.log(2) }
// 问:会打印出什么?
2 // 只打印 2,因为 f2 并不是 false,因为它是一个对象,而对象是 true
// 别忘记js中只有 NAN、null、undefined、''、0是false,而对象和其它的都是true
4. Object()
公共属性(原型)
1
2
3
4
5
6
7var n = new Numer(1)
var s = new String('a')
var b = new Boolean(true)
var o = new Object()
// 上面4个不同的对象都有`toString()、valueOf()`属性,可是如果每个对象都创建2个属性会很浪费内存,
// 所以,共用就好了
那么怎么访问公共属性呢?每个对象的toString储存公共属性的toString的地址?不proto
js通过隐藏属性__proto__
属性来访问公共属性,它指向了那些所有对象共有的属性
步骤:- 首先查看自身是否是对象,如果不是就包装对象
- 如果是对象就查看自身的 key 有没有 toString,有的话就直接调用
- 如果没有的话就通过
__proto__
查看你的共用属性看有没有,有的话就将你自身对应的值打印出来
例子:1
2
3
4
5
6
7var o1 = {name: 'zero'}
o1.toString() // [object Object]
// 依照步骤来,o1是对象,o1没有toString,查看共有属性,有toString,打印o1对应的值
// 不仅仅是o1,创建更多的对象也是一样,所有的对象都有隐藏属性`__proto__`,指向对应的共有属性
var o2 = {}
o1 === o2 // false
o1.toString() === o2.toString() // true
如果是Number对象呢?
1
2var n = new Number(11)
n.toString(16) // numer对象可以这样,而oject对象是不能这样toString(16)的
可以看见,Number重写了toString属性,以及添加一部分自己的属性,
然后通过__proto__
指向Object,对象共有属性
所以如同上图,Number对象就是在第3步去Number重写的属性寻找,没有的话去共有属性找
Number对象的__proto__
指向Number重写的共有属性,Number重写的共有属性的__proto__
指向对象共有属性- 除了Number以外,类似的还有String、Boolean(目前所学的)
原型链
- 对象的属性和方法,有可能定义在自身,也有可能定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain),就像我们上面画的图一样,
- 如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。Object.prototype 就是 Object对象的共有属性,相对的,Number.prototype就是Number对象的共有属性,而Number.prototype的proto又指向Object.prototype,也就是它的共有属性,String和Boolean也是如此
看这张图,结合前面所学的数据结构,是不是很有意思,
根节点是Object.prototype,三个子节点分别是String.prototype、Number.prototype、Boolean.prototype,
当你执行var str = new String('a')
时,浏览器就会在堆中创建一个hash,str保存这个hash的地址,
这个hash也就是String对象中除了你定义的属性外还有隐藏属性proto指向String.prototype,String.prototype又指向Object.prototype,这就完成了String API的所有绑定,
Number和Boolean也是一样 - “原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。
- 如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。
- 需要注意的是,一级级向上,在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。
prototype与proto
两者都指向共用属性
String.prototype 是 String 的共用属性的引用(防止共用属性被垃圾回收)
s.proto 是 String 的共用属性的引用(这是你在用共用属性)
proto 是对象的属性,prototype 是函数的属性
它们储存的地址相同,指向的其实是同一个对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 一些烧脑的东西
var obj1 = 函数.prototype
obj1.__proto__ === Object.prototype // 等于下面
函数.prototype.__proto__ === Object.prototype
var obj2 = 函数
obj2.__proto__ === Function.prototype // 也就是
函数.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
Function.prototype.__proto__ === Obeject.prototype
String.__proto__ === Function.prototype
Number.__proto__ === Function.prototype
Boolean.__proto__ === Function.prototype
Object.__proto__ === Function.prototype
总之,记住公式:1
2
3
4
5
6
7
8
9
10
11
12
13对象.__proto__ === (对象原型)函数.prototype
函数.__proto__ === Function.prototype
Function.prototype.__proto_ === Object.prototype
函数.prototype.__proto_ === Object.prototype
// 测试一下代码就可以证明
function fc(){}
var o = new fc()
o.__proto__ === fc.prototype
fc.__proto__ === Function.prototype
fc.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null也就是说:
- 所有对象的
__proto__
引用此对象原型函数的prototype
属性 - 所有函数的
__proto__
引用Function.protype
,不管你自己写的还是 api Function.protype.__proto__
以及你自己写的函数的共用属性prototype
的__proto__
引用Object.prototype
参考
- 所有对象的
- 那么,Object.prototype对象有没有它的原型呢?回答是有的,就是没有任何属性和方法的null对象,而null对象没有自己的原型。
Object.getPrototypeOf(Object.prototype) // null
上面代码表示,Object.prototype对象的原型是null,由于null没有任何属性,所以原型链到此为止。
Object.prototype 就是 Object对象的共有属性- 阮一峰
a21 JS 里的类型
类型转换
1. 转换为 字符串
toString()
方法返回一个表示该对象的字符串 MDN- 语法:
object.toString()
number to string
1
2var num = 1; // number
n.toString() // '1'boolean to string
1
2var boolean = true
boolean.toString() // 'true'symbol 这里不研究
null
1
2
3
4var n = null
n.toString()
// Uncaught TypeError: Cannot read property 'toString' of null
// 所以 null 类型并没有 toString() 这个 apiundefined
1
2
3
4var u = undefined
u.toString()
// Uncaught TypeError: Cannot read property 'toString' of null
// 所以 undefined 类型也没有 toString() 这个 apiobject
1
2
3var obj = {"name": "zero"}
obj.toString // "[object Object]"
// 可以 toString(), 但结果并不是我们想要的总结:想让一个东西变成字符串,如果它能变成一个字符串,那么直接调用 toString() 就可以了;
console.log()
也是用的这种原理,理论上console.log()
只能接受字符串1
2
3congole.log('zero') // zero ,这里浏览器打印出来的并不一定加括号
console.log(1) // 1 等于下面的
console.log((1).toString())object 对象的
key
也是这样,1
2
3
4
5var obj = {}
obj['name'] = 1
obj[1] = 2 // 1 被 toString()
obj[true] = 1 // true -> 'true'
obj // { 1: 2, name: 1, true: 1 }有些地方自动的、把它需要字符串就调用
toString()
,JS 里有很多这种地方但是使用 toSteing() 很麻烦,下面是老司机的方法,与空字符串相加
使用+
连接符,如果它的一边有字符串,它就会尝试将另外一边也变成字符串1
2
3
4
5
6
7
8
9
10
111 + '' // '1'
true + '' // 'true'
var obj = {}
obj + '' // '[Object Object]'
null + '' // 'null'
undefined + '' // 'undefined'
也可以翻过写
'' + 1 // '1'
'' + true // 'true'
...
这种方式甚至比 toString() 更强大,因为它能将 null 和 undefined 也变成字符串使用
String()
函数,可以将任意类型的值转化成字符串。转换规则如下。原始类型值的转换规则
数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为”true”,false转为”false”。
undefined:转为”undefined”。
null:转为”null”。1
2
3
4
5String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"对象的转换规则
String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
- 阮一峰
MDN2. 转换为 布尔值
Boolean()
函数,可以将任意类型的变量转为布尔值。(强制转换)它的转换规则相对简单:除了以下六个值的转换结果为false,其他的值全部为true。
undefined
null
-0
0或+0
NaN
‘’(空字符串)1
2
3
4
5
6
7Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean(1) // true
Boolean(' ') // true注意,所有对象(包括空对象)的转换结果都是true,甚至连false对应的布尔对象new Boolean(false)也是true。
1
2
3Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true所有对象的布尔值都是true,这是因为JavaScript语言设计的时候,出于性能的考虑,如果对象需要计算才能得到布尔值,对于obj1 && obj2这样的场景,可能会需要较多的计算。为了保证性能,就统一规定,对象的布尔值为true。
- 阮一峰
- MDN
- 老司机的简易方法
首先来看一段代码
!trur // false
(!
是取反的意思)
那么在前面再加一个!
!!true // true
得到这样一个结果(可以尝试理解负负得正)
于是我们得到一个结果,用任何一个东西给它取反两次就会得到它的布尔值1
2
3
4
5
6
7
8
9
10!1 // false
!!true // true
!!0 // false
!!1 // true
!!'' // false
!!' ' // true
!!null // false
!!undefined // false
!!{} // true
!!{name: 'zero'} // true它的规则和
Boolean()
是一样的,只有那几个值是’false’- falsy-MDN
3. 转换为Number
‘1’ -> 1
1
2
3
4
5
6
7
8
9
10
11
12
131. Number('1') === 1
2. parseInt('1', 10) === 1
3. parseFloat('1.23') === 1.23
// 老司机的简单方法
4. '1' - 0 === 1
5. + '1' === 1
6. -(- '1') === 1
// 还有一些需要注意的
parseInt('011') === 11
parseInt('011', 8) === 9
parseInt('011', 10) === 11
parseInt('12s') === 12
内存图
面试题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33var a = 1
var b = a
b = 2
请问 a 显示是几?
1
var a = {name: 'a'}
var b = a
b = {name: 'b'}
请问现在 a.name 是多少?
'a'
var a = {name: 'a'}
var b = a
b.name = 'b'
请问现在 a.name 是多少?
'b'
var a = {name: 'a'}
var b = a
b = null
请问现在 a 是什么?
{name: 'a'}
var a = {n: 1}
var b = a;
a.x = a = {n: 2} // 先计算 a = {n: 2},再计算 a.x = 值
// 难点在于,a = {n: 2}计算后,a储存的地址已经变了,
// 但是a.x的a的地址仍然是之前的地址,详见下图
alert(a.x) // undefined
alert(b.x) // [object Object]
// alert函数默认参数使用toString转换字符串垃圾回收
如果一个对象没有被引用,她就是垃圾,将被回收1
2
3
4var a = {name: 'a'}
var b = {name: 'b'}
a = b
// {name: 'a'} 失去引用,将被回收深复制
1
2
3
4
5var a = 1
var b = a
b = 2 //这个时候改变 b
a 完全不受 b 的影响
那么我们就说这是一个深复制对于简单类型的数据来说,赋值就是深拷贝。
对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。
1
2
3
4
5
6// 这是一个浅拷贝的例子
var a = {name: 'frank'}
var b = a
b.name = 'b'
a.name === 'b' // true
// 因为我们对 b 操作后,a 也变了什么是深拷贝了,就是对 Heap 内存进行完全的拷贝。
1
2
3
4var a = {name: 'frank'}
var b = deepClone(a) // deepClone 还不知道怎么实现
b.name = 'b'
a.name === 'a' // true
A20-js里的数据
非标准的语法
通过 Babel 来转义使用
将不存在的语法翻译成存在的语法js有 7 种数据类型
- 数值 number
- 字符串 string
- 布尔 boolean
- Symbol 符号
- null
- undefined
- 对象 object
array和function都是对象,除了前面6种其它都是对象
如何表示这7种数据类型
1. number
- 十进制 1、1.1、.1、1.23e2、1.23E2
- 二进制 0b、0B开头 0b10(十进制2)
- 八进制 0开头 011(十进制9)
- 十六进制 0x、0X开头 0x11(十进制17)
2. string
- ‘你好’
- “你好”
- ‘’空字符串
- ‘ ‘空格字符串
- ‘’’ 转义字符 输出单引号,\ 是转义符
- ‘n’回车 ‘\t’tab …… 这些都是一个字符
- ‘\’ 用转义符来转义转义符,输出 \
- 多行字符串
1
2
3
4
5
6
7
8
9
10
11
12var str = '1234\ 这个方法抄袭自命令行
67890' 输出1234567890 这种很容易出现空格但是看不见,很坑
var str = '12345' +
'67890' // 输出 1234567890,这种方法多达几个字符但是更好读更安全(只推荐这种)
ES6新增了一种新的语法,使用 反引号(1左边那个按键)
var str = `12345
67890` // 这种不需要加\,但是依然会出现空格,包括缩进产生的
var str = `12345
67890` // 因为有缩进所以依然有空格,并且这种方式保留 回车!
3. boolean
- 布尔其实是一个人的名字,他是一名数学家,他发明了逻辑学
- true 真
- false 假
- 相关:&&(与)、||(或) 运算
举例: a&&b
只有 a 和 b 同时为 真 的时候 a&&b 才为真
举例: a||b
只要 a 和 b 有一个为 真,结果就为 真
4. symbol(暂时用不上,没讲)
5. null (空对象)
- 这是一个类型
- 它只有一个值,就是 null
6. undefined (空非对象)
- 这是一个类型
- 它只有一个值,就是 undefined
null 与 undefined 的意思都是 什么也没有,
它们是 js 的一个bug,是没设计好区别
- 变量没有赋值 - 值为undefined (语法)
- 有一个对象object,现在不想赋值,那么给它一个 null (惯例)
(可以给undefined,但是推荐给 null)
有一个非对象,现在不像赋值,推荐给一个 undefined (不需要自己给,看第一条)
以上 6 种叫做 基本类型(简单类型,它们就一个值)
7. object
- 它是 复杂类型,由简单类型组成
举例:
1
2
3
4
5
6var person = {
"name": "zero", // js 只支持以 字符串 为key
"age": 20, // key可以不加引号,js会自动加上
"gender": "male", // es3不支持最后一个加逗号,es5支持,
// ie7及以下不能加,ie8及以上可以加
}语法:
- 用
{}
包起来 里面是 键值对
1
2
3
4{
key: value, // key必须是字符串,但是js会自动添加所以不手动添加也可以
…… // value 该怎么写就怎么写,
}然后将这个新建的对象赋给一个变量
1
2
3
4
5
6
7
8var obj = {
string: "string",
number: 10,
boolean: true,
obj2:{ // 对象里面还可以有另一个对象,一直嵌套下去
name:'xxx',
}
}使用
obj['string']
obj.number
烧脑的地方来了,里面的值可不可以是自己呢?
1
2
3
4
5var person = {
name: 'zero',
age:'22',
self: person
}输出 person.self.self.self.self.name 会是什么结果
undefined,person中储存的是地址,指向的堆中只有一个对象,
由于还未将对象赋给person,
var person; // 变量提升别忘了
person = {…} // 先计算对象,然后赋给person地址,因此self的值实际上是undefined,
即使先赋值再添加self,引用的仍然是同一个对象,self指向的都是同一个地址空字符串也是字符串,那么空字符串当key可以么?
1
2
3var obj = {
"": "空字符串"
}使用:obj[“”] 就能输出 “空字符串”
- 还是key,变量名不可以用数字开头,key可以么
不加引号的key不可以,不加引号的key默认使用标识符的命名规则
加引号的key可以,中间加空格也可以,”a b”: ‘xxx’, - 很重要的一点
如果key的书写符合标识符的规则的话
比如:1
2
3
4var person = {
name: 'zero',
age: 22
}
可以这样使用:`person.name、person.age // 这里name、age都是字符串,``
(特例,只有符合标识符的情况下才可以这样使用)- 用
delete
可以删除对象的属性,比如
delete person[‘name’] (上面那种特里也可以,规则不变)
person.name // undefined (无value)
‘name’ in person // false (无key)for in
- 遍历对象
- 使用,比如便利上面的person
1
2
3for(var key in person){
console.log(person[key]) // 不可以用person.key,因为key不是字符串,
}// 遍历输出的顺序并不一定是像代码那样的顺序
typeof
- 用来知道一个变量的类型
- typeof 返回null时会返回 ‘object’ ,第一个bug
typeof null // 'object'
- js中只有 7 中类型
但是typeof 函数的时候却会返回 function, 第二个bug
`typeof function(){} // ‘function’ (数组正常的返回object)``
初识HTML
1. 万维网联盟(World Wide Web Consortium, W3C),又称 W3C 理事会,是万维网的主要国际标准组织。
历史
万维网联盟(W3C)由蒂姆·伯纳斯-李于1994年10月离开欧洲核子研究中心(CERN)后成立,在欧盟执委会和国防高等研究计划署(DARPA)的支持下成立于麻省理工学院MIT计算机科学与人工智能实验室(MIT/LCS),DARPA曾率先推出了互联网及其前身ARPANET。
标准
为解决web应用中不同平台、技术和开发者带来的不兼容问题,保障Web信息的顺利和完整流通,万维网联盟制定了一系列标准并督促Web应用开发者和内容提供者遵循这些标准。标准的内容包括使用语言的规范,开发中使用的导则和解释引擎的行为等等。W3C也制定了包括XML和CSS等的众多影响深远的标准规范。
2. MDN Web Docs(旧称Mozilla Developer Network、Mozilla Developer Center,简称MDN)是一个汇集众多Mozilla基金会产品和网路技术开发文档的免费网站。
网站最初的内容是由DevEdge提供,但在AOL收购Netscape后,DevEdge网站也宣布关闭。为此Mozilla基金会向AOL取得了DevEdge释出的内容,同时将DevEdge内容搬移到mozilla.org。
MDN本身有一个论坛,并在Mozilla IRC 网络上有一个 IRC 频道#mdn。MDN由Mozilla公司提供服务器和员工的资助。
2016年10月3日发表的Brave网页浏览器将MDN作为其搜寻引擎选项之一。
3. HTML元素
以下是一部分html元素,考虑到时间我并没有写这些元素各自所代表的含义(其实就是懒,但是真的太麻烦啦!),如果你想要明白它们所代表的含义的话,就去MDN看吧!MDN-HTML1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134<a>
<abbr>
<acronym>
<address>
<applet>
<area>
<article>
<aside>
<audio>
<b>
<base>
<basefont>
<bdi>
<bdo>
<bgsound>
<big>
<blink>
<body>
<br>
<button>
<canvas>
<caption>
<center>
<cite>
<code>
<col>
<colgroup>
<content>
<data>
<dd>
<del>
<details>
<dfn>
<dialog>
<dir>
<div>
<dl>
<dt>
<element>
<em>
<embed>
<fieldset>
<figcaption>
<figure>
<font>
<footer>
<form>
<frame>
<frameset>
<head>
<header>
<hgroup>
<hr>
<html>
<i>
<iframe>
<image>
<img>
<input>
<ins>
<isindex>
<kbd>
<keygen>
<label>
<legend>
<li>
<link>
<listing>
<main>
<map>
<mark>
<marquee>
<menu>
<menuitem>
<meta>
<meter>
<multicol>
<nav>
<nextid>
<nobr>
<noembed>
<noframes>
<noscript>
<object>
<ol>
<optgroup>
<option>
<output>
<p>
<param>
<picture>
<plaintext>
<pre>
<q>
<rp>
<rt>
<rtc>
<ruby>
<s>
<samp>
<script>
<section>
<select>
<shadow>
<slot>
<small>
Source
<spacer>
<span>
<strike>
<strong>
<style>
<sub>
<summary>
<sup>
<table>
<tbody>
<td>
<template>
<textarea>
<tfoot>
<th>
<thead>
<time>
<title>
<tr>
<track>
<tt>
<u>
<ul>
<var>
<video>
<wbr>
<xmp>
4.空标签
虽然不能一个一个解释下每个标签的含义,但是可以解释一些特别的东西。
空标签就是这种“特别”之一。
正常情况下,一个 HTML 元素通常由一个开始标记和结束标记组成,其内容插入在:<tagname> 内容xxx</tagname>
例如:<p>A Paragraph</p>
但是空标签不同,它没有内容和结束标记!
在HTML中,对一个空标签使用一个闭标签通常时无效的。
例如:<input type="text"></inut>
正确的写法是:<input type="text">
当然你也可以这么写:<input type="text" />
(HTML5不需要关闭空元素但是你可以这么做,如果你需要一个更严格的验证的话)
在HTML中还有以下这些空元素:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<area>
<base>
<br>
<col>
<colgroup> when the span is present
<command>
<embed>
<hr>
<img>
<input>
<keygen>
<link>
<meta>
<param>
<source>
<track>
<wbr>
5. 可替换标签
从元素本身的特点来讲,HTML标签元素可以分为可替换元素(replaceable element)和不可替换元素(none-replaceable element)。
不可替换元素:
HTML中的大多数元素是不可替换元素,即其内容直接表现给用户端(例如浏览器)。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 > 段落```<p>```是一个不可替换元素,文字“段落的内容”全被显示。
**可替换元素:**
可替换元素就是浏览器根据元素的标签和属性,来决定元素的具体显示内容。
> 例如浏览器会根据```<img>```标签的src属性的值来读取图片信息并显示出来,而如果查看(x)html代码,
> 则看不到图片的实际内容;又例如根据```<input>```标签的type属性来决定是显示输入框,还是单选按钮等。
更详细的解释(从[CSS2.1规范](https://www.w3.org/TR/CSS21/conform.html)):
> 内容超出CSS格式模型范围的元素,如图像,嵌入式文档或小程序。
> 例如,HTML IMG元素的内容通常被其“src”属性指定的图像取代。
> 替换的元素通常具有固有的尺寸:固有宽度,固有高度和固有比率。
> 例如,位图图像具有以绝对单位指定的固有宽度和固有高度(从中可明显确定固有比率)。
> 另一方面,其他文档可能没有任何固有的尺寸(例如,空白的HTML文档)。
> 如果认为这些维度可能会泄露敏感信息给第三方,用户代理可能会认为被替换的元素没有任何内在维度。
> 例如,如果一个HTML文档根据用户的银行余额改变了内在大小,那么UA可能希望这个资源没有固有维度。
> CSS渲染模型中不考虑替换元素的内容。
常见的可替换元素有:
Hexo+GitHub博客搭建
如何使用Hexo+GitHub搭建一个博客
首先要声明的是本文默认你已经有git账号并且已经搞定ssh之类。
并且是仅有一个git账户或者本机只有一个git全局账户的情况下!!!(至于为何……因为我还没搞定一套电脑两个账户怎么折腾……)
以下是步骤
- 在github上新建一个空的repo,repo 名称是「你的用户名.github.io」(请将你的用户名替换成真正的用户名)
进入一个安全的目录,你可以在D盘或者其它某个磁盘下创建一个文件夹,然后进入这个文件夹,比如我是D盘:
打开git bash1
2
3cd d:
mkdir myblog
cd myblog然后安装hexo
npm install -g hexo-cli
- 初始化,
hexo init
- 安装(我也不知道安装什么),
npm i
hexo new 开博大吉
,你会看见一个md文件的路径start xxxxxxxxx.md
,编辑这个md文件,你也可以手动去翻文件夹然后编辑start _config.yml
,编辑网站配置- 把第六行的title改成你想要的名字
- 把第九行的author改成你的名字
- 把最后一行的type改成type: git
- 在最后一行后面新增一行,左边与 type 平齐,加上一行
repo: 仓库地址
请将仓库地址改为「你的用户名.github.io」对应的仓库地址,仓库地址以 git@github.com: 开头
npm install hexo-deployer-git --save
,安装git部署插件hexo deploy
- 进入「你的用户名.github.io」对应的 repo,打开 GitHub Pages 功能,默认应该是打开的,如果是,就直接点击预览
- 你现在应该看到了你的博客!
第二篇博客
hexo new 第二篇博客
- 复制显示路径。使用
start 路径
来编辑它 hexo generate
hexo deploy
- 去看看你的博客,应该能看见第二篇博客了
换主题
- 主题 这是一个主题合集
- 随便找一个主题合集,进入主题的github首页,比如我找的是
git@github.com:xiangming/landscape-plus.git - 复制它的 SSH 地址或 HTTPS 地址,假设地址为 git@github.com:iissnan/hexo-theme-next.git
cd themes
git clone git@github.com:iissnan/hexo-theme-next.git
cd ..
- 将 _config.yml 的第 75 行改为
theme: landscape-plus.git
,保存 hexo g
hexo d
- 等上一会,然后刷新你的博客页面,你就会看到一个新的外观。如果不喜欢这个主题,就回到第一步,重选一个主题再来一遍。
以上就是使用Hexo配合GitHub搭建个人博客的教程了。
Hello World
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
Quick Start
Create a new post
1 | $ hexo new "My New Post" |
More info: Writing
Run server
1 | $ hexo server |
More info: Server
Generate static files
1 | $ hexo generate |
More info: Generating
Deploy to remote sites
1 | $ hexo deploy |
More info: Deployment