一、html语义化
优点:
1、易修改、易维护
2、无障碍阅读
3、搜索引擎友好,易于SEO
4、面向未来的HTML、以后可能有更多的支持
标签
header: 标注内容的标题、标注网页的页眉
nav:导航栏、一组文章的链接
main:主要内容
footer: 可以包含版权、来源信息、法律限制等等之类的文本或链接信息
aside:侧边栏、与内容无关联的附注解释某个观点或者其他的内容链接
section: 与页面主体并列显示的小内容块;独立性内容,清单、表单等;分组内容,如 CMS 系统中的文章分类区块;比较长文档的一部分,可能仅仅是为了正确规定页面大纲
article: 表示一个完整的、自成一体的内容块
figure: 插图
figcaption: 包含了关于插图的详细解释
二、CSS选择器
类型:id选择器、类选择器(class)、标签选择器(div)、相邻选择器(a+b)、父子选择器(a>b)、后代选择器(a b)、通配符选择器(*)、属性选择器(a[rel="external"])、伪类选择器(a:hover, li:nth-child)伪元素选择器(::before)
权重:!important > 行内样式>ID选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签 = 伪元素选择器 > 通配符 > 继承 > 浏览器默认属性同一级别
三、BFC
格式化上下文
浮动元素和绝对定位元素,非块级盒子的块级容器(例如inline-blocks,table-cells,和table-captions),以及overflow值不为”visiable”的块级盒子,都会为他们的内容创建新的BFC(Block Fromatting Context,即块级格式上下文)
渲染规则
(1)BFC垂直方向边距重叠
(2)BFC的区域不会与浮动元素的box重叠
(3)BFC是一个独立的容器,外面的元素不会影响里面的元素
(4)计算BFC高度的时候浮动元素也会参与计算
解决问题
父元素塌陷、下边距重合等用创建BFC解决例如父元素加overflow hidden
宽度高度未知的水平垂直居中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> /* 第一种 */ /* .box { display: flex; display: -webkit-flex; border: 1px solid #0000ff; height: 400px; 400px; align-items: center; justify-content: center; } */ /* 第二种 */ /* .box { display: flex; display: -webkit-flex; border: 1px solid #0000ff; height: 400px; 400px; } .item { margin: auto; } */ /* 第三种 */ /* .box { position: relative; border: 1px solid #0000ff; height: 400px; 400px; } .item { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } */ /* 第四种 */ /* .box { border: 1px solid #0000ff; height: 400px; 400px; display: table-cell; text-align: center; vertical-align: middle; } */ /* 第五种 */ /* .box { border: 1px solid #0000ff; height: 400px; 400px; display: grid; } .item { align-self: center; justify-self: center; } */ /* 第六种 */ .box { border: 1px solid #0000ff; height: 400px; width: 400px; text-align: center; font-size: 0; } .box::before { content: ''; display: inline-block; vertical-align: middle; height: 100%; } .item { vertical-align: middle; display: inline-block; font-size: 16px; } </style> </head> <body> <div class="box"> <div class="item">horizontal and vertical</div> </div> </body> </html>
三、数据类型
8种:Boolean、Undefined、Number、BigInt、String、Symbol、Null、Object
BigInt :Number是-9007199254740991 -(2^53-1)
至9007199254740991(2^53-1)之间的双精度64位浮点数,如果超出就会出现失去精度的问题,例如9007199254740992 === 9007199254740993返回true,可以使用9007199254740992n
Symbol:一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名,因为 Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。
let sy = Symbol("KK"); console.log(sy); // Symbol(KK) typeof(sy); // "symbol" // 相同参数 Symbol() 返回的值不相等 let sy1 = Symbol("KK"); sy === sy1; // false
由于每一个 Symbol 的值都是不相等的,所以 Symbol 作为对象的属性名,可以保证属性不重名。
let sy = Symbol("key1"); // 写法1 let syObject = {}; syObject[sy] = "kk"; console.log(syObject); // {Symbol(key1): "kk"} // 写法2 Symbol 作为对象属性名时不能用.运算符,要用方括号。因为.运算符后面是字符串,所以取到的是字符串 sy 属性,而不是 Symbol 值 sy 属性 let syObject = { [sy]: "kk" }; console.log(syObject); // {Symbol(key1): "kk"} // 写法3 let syObject = {}; Object.defineProperty(syObject, sy, {value: "kk"}); console.log(syObject); // {Symbol(key1): "kk"}
Symbol 值作为属性名时,该属性是公有属性不是私有属性,可以在类的外部访问。但是不会出现在 for...in 、 for...of 的循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。
let syObject = {}; syObject[sy] = "kk"; console.log(syObject); for (let i in syObject) { console.log(i); } // 无输出 Object.keys(syObject); // [] Object.getOwnPropertySymbols(syObject); // [Symbol(key1)] Reflect.ownKeys(syObject); // [Symbol(key1)]
使用 Symbol 定义常量,可以保证常量的唯一
const COLOR_RED = Symbol("red");
const COLOR_YELLOW = Symbol("yellow");
Symbol.for() 类似单例模式,首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值,如果有即返回该 Symbol 值,若没有则新建并返回一个以该字符串参数为名称的 Symbol 值,并登记在全局环境中供搜索。
Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ,用来检测该字符串参数作为名称的 Symbol 值是否已被登记。
let yellow = Symbol("Yellow"); let yellow1 = Symbol.for("Yellow"); yellow === yellow1; // false let yellow2 = Symbol.for("Yellow"); yellow1 === yellow2; // true Symbol.keyFor(yellow1); // "Yellow"
四、事件模型
捕获阶段、目标阶段、冒泡阶段
目标阶段执行事件发生在捕捉之后,是冒泡之前还是之后和执行事件函数的绑定位置有关
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="s1" style=" 500px; height: 500px; display: flex; align-items: center; justify-content: center; background-color: aquamarine"> 父集 <div id="s2" style=" 200px; height: 200px; background-color: gold">子集</div> </div> <script> s1.addEventListener('click', e => printHandle(e, '父集 冒泡事件'), false); s1.addEventListener('click', e => printHandle(e, '父集 捕获事件'), true); s2.addEventListener('click', e => printHandle(e, '子集 冒泡事件1'), false); s2.onclick = () => console.log('执行事件'); s2.addEventListener('click', e => printHandle(e, '子集 捕获事件'), true); s2.addEventListener('click', e => printHandle(e, '子集 冒泡事件2'), false); const printHandle = (e, text) => { // 阻止事件冒泡 // if (e.stopPropagation) { // e.stopPropagation(); // } else { // e.cancelBubble(); // } console.log(text); }; </script> </body> </html>
五、ES6 let 和const
let 不可重复声明定义,var可以
const 声明时必须赋值,且值不可更改
let 和const 不会变量提升
var 会变量提升
for 循环中使用let 可保证值的改变,let 有块作用域
for (var i = 0; i < 10; i++) { setTimeout(function(){ console.log(i); }) } // 输出十个 10 for (let j = 0; j < 10; j++) { setTimeout(function(){ console.log(j); }) } // 输出 0123456789
变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i, 每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以此时的 i 都是 10。
变量 j 是用 let 声明的,当前的 j 只在本轮循环中有效,每次循环的 j 其实都是一个新的变量,所以 setTimeout 定时器里面的 j 其实是不同的变量,即最后输出 12345。(若每次循环的变量 j 都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript 引擎内部会记住前一个循环的值)。
六、ES6 Map Set
Map
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
与Object的差别
1. Object只能用字符串或者symbol作为key值,Map无限制
2.Map中的键值是有序的(FIFO 原则),而添加到对象中的键则不是
3.Map的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算
var myMap = new Map(); var keyString = "a string"; myMap.set(keyString, "和键'a string'关联的值"); myMap.get(keyString); // "和键'a string'关联的值" myMap.get("a string"); // "和键'a string'关联的值" // 因为 keyString === 'a string' var myMap = new Map(); var keyObj = {}, myMap.set(keyObj, "和键 keyObj 关联的值"); myMap.get(keyObj); // "和键 keyObj 关联的值" myMap.get({}); // undefined, 因为 keyObj !== {} var myMap = new Map(); var keyFunc = function () {}, // 函数 myMap.set(keyFunc, "和键 keyFunc 关联的值"); myMap.get(keyFunc); // "和键 keyFunc 关联的值" myMap.get(function() {}) // undefined, 因为 keyFunc !== function () {} var myMap = new Map(); myMap.set(NaN, "not a number"); myMap.get(NaN); // "not a number" var otherNaN = Number("foo"); myMap.get(otherNaN); // "not a number"
虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true),NaN作为Map的键来说是没有区别的。
for of
var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); // 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one" for (var [key, value] of myMap) { console.log(key + " = " + value); } for (var [key, value] of myMap.entries()) { console.log(key + " = " + value); } /* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */ // 将会显示两个log。 一个是 "0" 另一个是 "1" for (var key of myMap.keys()) { console.log(key); } /* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */ // 将会显示两个log。 一个是 "zero" 另一个是 "one" for (var value of myMap.values()) { console.log(value); } /* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */
forEach
var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); // 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one" myMap.forEach((value, key) => console.log(key + " = " + value))
Map与二维数组之间的转换
Aarry.form(map) 解构[...map] 和 new Map(arr)
Map的克隆
new Map(map)
Map的合并
new Map([...mapA, ...mapB])
Set
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
let mySet = new Set(); mySet.add(1); // Set(1) {1} mySet.add(5); // Set(2) {1, 5} mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性 mySet.add("some text"); // Set(3) {1, 5, "some text"} 这里体现了类型的多样性 var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); // Set(5) {1, 5, "some text", {…}, {…}} // 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储// Array 转 Set var mySet = new Set(["value1", "value2", "value3"]); // 用...操作符,将 Set 转 Array var myArray = [...mySet]; String // String 转 Set var mySet = new Set('hello'); // Set(4) {"h", "e", "l", "o"} // 注:Set 中 toString 方法是不能将 Set 转换成 String
可以用作数组去重等
var mySet = new Set([1, 2, 3, 4, 4]); [...mySet]; // [1, 2, 3, 4]
七、其他ES6补充
// includes、startsWith、endsWith、repeat、padStart、padEnd let string = 'apple,banana,orange'; string.includes('banana'); // true string.startsWith('apple'); // true string.endsWith('apple'); // false string.startsWith('banana', 6); // true console.log('Hello,'.repeat(2)); // "Hello,Hello," console.log('h'.padStart(5, 'o')); // "ooooh" console.log('h'.padEnd(5, 'o')); // "hoooo" console.log('h'.padStart(5)); // " h"
indexOf lastIndexOf 查找数组或字符串中某个对象出现的位置和最后位置
数值的指数运算 2**3 = 8
八、JS中的this
// 1.全局对象中的this { const obj = { a: { b: { c: this } } }; console.log('全局对象中的this, window', obj.a.b.c == window); } // 2.全局函数中的this { function fun() { function fun1() { console.log('全局函数中的this, window', this === window); } fun1(); } fun(); } // 3.全局对象中函数的this { const obj = { fun() { console.log('全局对象中函数的this, obj', this === obj); } }; obj.fun(); } // 4.全局函数中的对象的this { function fun() { const obj = { a: 1, c: this }; console.log('全局函数中的对象的this, window', obj.c === window); } fun(); } // 5.全局对象中调用函数中调用函数的this { const obj = { fun() { function fun1() { function fun2() { console.log('全局对象中调用函数中调用函数的this, window', this === window); } fun2(); } fun1(); } }; obj.fun(); } // 6.关键是执行时的this指向 { const obj = { objIn: { obj: 'objIn', fun() { return this; } } }; console.log('关键是执行时的this指向, objIn', obj.objIn.fun() === obj.objIn); const fun = obj.objIn.fun; console.log('关键是执行时的this指向, window', fun() === window); } // window.obj.obj.obj(this) => window 全局声明的对象下的属性this指向全局对象 // window.fun(fun(this)) => window 函数的this指向调用函数的对象, fun1() 调用对象是window // window.obj fun(this) => obj 函数的this指向调用函数的对象, obj.fun() 调用对象是obj // window.fun(obj(this)) => window 函数调用 fun() this指向window, window下声明的obj中属性this指向window // window.obj.fun() =>window 全局声明的对象下的函数this指向全局对象 // window.obj.objIn.fun(this) => 函数的this指向调用函数的对象, objIn.fun() objIn
1.JavaScript的this
是在调用阶段进行绑定
2.严格模式下this是指向undefined,在非严格版中this指向undefined时默认自动指向全局对象(浏览器中就是window)
3.函数的this指向执行函数的对象
4.对象中的this执行声明对象的所在对象
5.new操作符会改变函数this的指向
function Fun() { //new做的事情 const obj = {}; obj.__proto__ = Fun.prototype; //Base为构造函数 //一系列赋值以及更多的事 obj.name = 'Daming' ... return obj; }
this
值,作为自己的 this
值{ const obj = {}; const fun = () => console.log('=>', this === window ? 'window' : 'obj'); const fun1 = function () { console.log('()', this === window ? 'window' : 'obj'); }; fun(); fun.call(obj); fun1(); fun1.call(obj); } console.log('---------我是分割线--------'); { const obj = {}; function fun() { let f = () => console.log('=>', this === window ? 'window' : 'obj'); f(); } function fun1() { let f = function () { console.log('()', this === window ? 'window' : 'obj'); }; f(); } fun(); fun.call(obj); fun1(); fun1.call(obj); } console.log('---------我是分割线--------'); { function Fun() { this.name = 'Damonare'; } Fun.prototype.say = () => { console.log('=>', this === window ? 'window' : 'obj'); }; function Fun1() { this.name = 'Damonare'; } Fun1.prototype.say = function () { console.log('()', this === window ? 'window' : 'obj'); }; const f = new Fun(); f.say(); const f1 = new Fun1(); f1.say(); } console.log('---------我是分割线--------'); { function Fun() { this.name = 'Damonare'; this.say = () => { console.log('=>', this === window ? 'window' : 'obj'); }; } function Fun1() { this.name = 'Damonare'; this.say = function () { console.log('()', this === window ? 'window' : 'obj'); }; } const f = new Fun(); f.say(); const f1 = new Fun1(); f1.say(); }
九、变量提升问题
var a = 1; function fn() { if (!a) { var a = 123; } console.log(a); } fn(); // ----------------------- var a; function fn() { if (!a) { var a = 123; } console.log(a); } a = 1; fn(); // 123 function Foo() { getName = function () { console.log('1'); }; return this; } Foo.getName = function () { console.log('2'); }; Foo.prototype.getName = function () { console.log('3'); }; var getName = function () { console.log('4'); }; function getName() { console.log('5'); } Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); // ----------- // 变量提升转换 function Foo() { getName = function () { console.log('1'); }; return this; } function getName() { console.log('5'); } var getName; Foo.getName = function () { console.log('2'); }; Foo.prototype.getName = function () { console.log('3'); }; getName = function () { console.log('4'); }; // 执行 Foo.getName(); // 2 getName(); // 4 Foo().getName(); // 1 getName(); // 1 new Foo.getName(); // 2 new Foo().getName(); // 3