HTML+CSS+JS知识点总结

1,485 阅读8分钟

一、HTML+CSS

1. 如何理解HTML的语义化

  • 让人更容易读懂(增加代码可读性)。
  • 让搜索引擎更容易读懂,有助于爬虫抓取更多的有效信息,爬虫依赖于标签来确定上下文和各个关键字的权重(SEO)。
  • 在没有 CSS 样式下,页面也能呈现出很好地内容结构、代码结构。

2. 从浏览器地址栏输入url回车会发生什么

  • 输入 URL 后解析出协议、主机、端口、路径等信息,并构造一个 HTTP 请求。
  • DNS 域名解析。
  • TCP 连接。
  • http 请求。
  • 服务器处理请求并返回 HTTP 报文。
  • 浏览器渲染页面
  • 断开 TCP 连接。

3. 溢出的文字显示省略号

  1. 单行
  • 先强制一行显示white-space:noweap
  • 超出的部分隐藏overflow:hidden
  • 超出的部分用省略号显示text-overflow:ellipsis
  1. 多行
overflow:hidden;
text-overflow:ellipsis;
display: -webkit-box;弹性伸缩盒子模型显示
-webkit-line-clamp:2;//限制在一个块元素显示的文本行数
-webkit-box-orient:vertical;//设置或检索伸缩对象子元素排序

4. css选择器和优先级

大家都知道样式的优先级一般为 !important > style > id > class

css选择器
选择器示例
类型选择器 h1 {  }
通配符选择器* {  }
类选择器 .box {  }
ID选择器 #unique { }
标签属性选择器a[title] {  }
伪类选择器p:first-child { }
伪类选择器 p::first-line { }
后代选择器article p
子代选择器 article > p
相邻兄弟选择器 h1 + p
通用兄弟选择器选择器h1 ~ p

5. BFC

BFC 即块级格式上下文,这是一个独立渲染的区域,规定了内部如何布局,并且这个区域的子元素不会影响到外面的元素,其中比较重要的布局规则有内部box垂直放置,计算BFC高度的时候,浮动元素也参与计算。 BFC 具有一些特性:

  1. 块级元素会在垂直方向一个接一个的排列,和文档流的排列方式一致。
  2. 在 BFC 中上下相邻的两个容器的 margin  会重叠,创建新的 BFC 可以避免外边距重叠。
  3. 计算 BFC 的高度时,需要计算浮动元素的高度,可以避免高度塌陷。
  4. BFC 区域不会与浮动的容器发生重叠。
  5. 每个元素的左 margin  值和容器的左 border  相接触。
  • 利用 4  和 5 ,我们可以实现三栏(或两栏)自适应布局。

创建 BFC 的方式:

  • 绝对定位元素(positionabsolutefixed )。
  • displayinline-block; table-cell; table-caption; flex; inline-flex
  • overflow 的值不为 visible

6. 水平垂直居中的方法

  1. 利用绝对定位,设置 left: 50%  和 top: 50%  现将子元素左上角移到父元素中心位置,然后再通过 translate  来调整子元素的中心点到父元素的中心。
  2. 利用绝对定位,子元素所有方向都为 0 ,将 margin  设置为 auto ,由于宽高固定,对应方向实现平分,该方法必须盒子有宽高
  3. 利用绝对定位,设置 left: 50% 和 top: 50% 现将子元素左上角移到父元素中心位置,然后再通过 margin-left  和 margin-top  以子元素自己的一半宽高进行负值赋值。该方法必须定宽高

二、JavaScript

1. 基本数据类型

在 JS 中共有 8  种基础的数据类型,分别为: Undefined 、 Null 、 Boolean 、 Number 、 String 、 Object 、 Symbol(ES6新增,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。) 、 BigInt(表示任意大小的整数)。

1.1 值类型和引用型数据的理解

  • 值类型是直接存储在中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
  • 引用类型存储在中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;

1.2 数据类型的判断

  • typeof:能判断所有值类型,函数。不可以对 null、对象、数组进行精确判断,因为都返回 object 。
console.log(typeof undefined); // undefined
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof Symbol("foo")); // symbol
console.log(typeof 2172141653n); // bigint
console.log(typeof function () {}); // function
// 不能判别
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object

  • instanceof:能判断对象类型,不能判断基本数据类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。
  • Object.prototype.toString.call() :所有原始数据类型都是能判断的,还有 Error 对象,Date 对象等。
Object.prototype.toString.call(2); // "[object Number]"
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(Math); // "[object Math]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function () {}); // "[object Function]"

1.3 如何判断数组

Array.isArray(arr); // true
arr.__proto__ === Array.prototype; // true
arr instanceof Array; // true
Object.prototype.toString.call(arr); // "[object Array]"

2. 数组的使用

数组API
一、数组序列化
  1. toString() 在默认情况下都会以逗号分隔字符串的形式返回数组项
  2. join() 使用指定的字符串用来分隔数组字符串
var arr = [1,5,2,8,10,{a:1}];
console.log(arr);//[ 1, 5, 2, 8, 10, { a: 1 } ]
console.log(arr.toString());//”1,5,2,8,10,[object Object]”
console.log(arr.join(""));//”152810[object Object]”
console.log(arr.join("-"));//”1-5-2-8-10-[object Object]”
二、栈和队列方法
  1. push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
  2. pop() 方法用于删除数组的最后一个元素并返回删除的元素。
  3. shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值
  4. unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
三、排列方法
  1. reverse() 方法用于颠倒数组中元素的顺序。
  2. sort() 方法用于对数组的元素进行排序。
  // 1. 翻转数组
        var arr = ['pink', 'red', 'blue'];
        arr.reverse();
        console.log(arr);

        // 2. 数组排序(冒泡排序)
        var arr1 = [13, 4, 77, 1, 7];
        arr1.sort(function(a, b) {
            //  return a - b; 升序的顺序排列
            return b - a; // 降序的顺序排列
        });
        console.log(arr1);
四、操作方法
  1. concat() 方法用于连接两个或多个数组。
  2. substr()方法用于截取指定的一段字符
  3. slice() 方法可从已有的数组中返回选定的元素。
  4. splice() 方法用于添加或删除数组中的元素。
 var str = 'andy';
        console.log(str.concat('red'));//andyred

        // 2. substr('截取的起始位置', '截取几个字符');
        var str1 = '改革春风吹满地';
        console.log(str1.substr(2, 2)); // 春风
五、位置方法
  1. indexOf() 方法可返回数组中某个指定的元素位置,找不到则返回-1。
  2. lastIndexOf() 方法可返回一个指定的元素在数组中最后出现的位置,从该字符串的后面向前查找。
var arr = ['red', 'green', 'pink'];
        console.log(arr.indexOf('blue'));//-1
        // 返回数组元素索引号方法  lastIndexOf(数组元素)  作用就是返回该数组元素的索引号 从后面开始查找
        var arr = ['red', 'green', 'blue', 'pink', 'blue'];
        console.log(arr.lastIndexOf('blue')); // 4

用indexOf()实现数组去重

 function unique(arr) {
            var newArr = [];
            for (var i = 0; i < arr.length; i++) {
                if (newArr.indexOf(arr[i]) === -1) {
                    newArr.push(arr[i]);
                }
            }
            return newArr;
        }
  
        var demo = unique(['blue', 'green', 'blue'])
        console.log(demo);
六、迭代方法
  1. every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
  2. some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
  3. filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
  4. map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
  5. forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。

2.1 利用函数求任意个数的最大值

function getMax() { 
            var max = arguments[0];
            for (var i = 1; i < arguments.length; i++) {
                if (arguments[i] > max) {
                    max = arguments[i];
                }
            }
            return max;
        }
        console.log(getMax(1, 2, 3));

2.2 利用函数翻转任意数组 reverse 翻转

 function reverse(arr) {
            var newArr = [];
            for (var i = arr.length - 1; i >= 0; i--) {
                newArr[newArr.length] = arr[i];
            }
            return newArr;
        }
        var arr1 = reverse([1, 3, 4, 6, 9]);
        console.log(arr1);
        var arr2 = reverse(['red', 'pink', 'blue']);
        console.log(arr2);

2.3 利用函数冒泡排序 sort 排序

 function sort(arr) {
            for (var i = 0; i < arr.length - 1; i++) {
                for (var j = 0; j < arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {
                        var temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
        var arr1 = sort([1, 4, 2, 9]);
        console.log(arr1);

2.4 利用函数判断闰年

function isRunYear(year) {
            // 如果是闰年我们返回 true  否则 返回 false 
            var flag = false;
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                flag = true;
            }
            return flag;
        }
        console.log(isRunYear(2000));

2.5 利用函数判断闰年

 function backDay() {
            var year = prompt('请您输入年份:');
            if (isRunYear(year)) { // 调用函数需要加小括号
                alert('当前年份是闰年2月份有29天');
            } else {
                alert('当前年份是平年2月份有28天');
            }
        }
        backDay();


        // 判断是否为闰年的函数
        function isRunYear(year) {
            // 如果是闰年我们返回 true  否则 返回 false 
            var flag = false;
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                flag = true;
            }
            return flag;
        }

2.6 利用set方法数组去重

function unique(arr){
    var arr2 = arr.sort();
    var res = [arr2[0]];
    for(var i=1;i<arr2.length;i++){
        if(arr2[i] !== res[res.length-1]){
        res.push(arr2[i]);
    }
}
return res;
}
//利用下标查询
 function unique(arr){
    var newArr = [arr[0]];
    for(var i=1;i<arr.length;i++){
        if(newArr.indexOf(arr[i]) == -1){
        newArr.push(arr[i]);
    }
}
return newArr;
}

3. 作用域和作用域链

  • 作用域 :就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突
  1. js的作用域(es6)之前 : 全局作用域 局部作用域
  2. 全局作用域: 整个script标签 或者是一个单独的js文件
  3. 局部作用域(函数作用域) 在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用
  • 作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链 就近原则 案例:
        // 案例1 : 结果是几?
        function f1() {
            var num = 123;

            function f2() {
                var num = 0;
                console.log(num); //num=0 站在目标出发,一层一层的往外查找
            }
            f2();
        }
        var num = 456;
        f1();
        // 案例2 :结果是几?
        var a = 1;

        function fn1() {
            var a = 2;
            var b = '22';
            fn2();

            function fn2() {
                var a = 3;
                fn3();

                function fn3() {
                    var a = 4;
                    console.log(a); //a=4
                    console.log(b); //b=22
                }
            }
        }
        fn1();

3.1 预解析

  1. 我们js引擎运行js 分为预解析、代码执行
  • 预解析 js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
  • 代码执行 按照代码书写的顺序从上往下执行
  1. 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
  • 变量提升就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
  • 函数提升就是把所有的函数声明提升到当前作用域的最前面 不调用函数 案例:
    var num = 10;
       fun();

        function fun() {
             console.log(num);
             var num = 20;
         }
        //  相当于执行了以下操作
        var num;

        function fun() {
             var num;
            console.log(num);
             num = 20;
         }
         num = 10;
         fun();
        // // 案例2
         var num = 10;

         function fn() {
            console.log(num);
             var num = 20;
             console.log(num);
         }
         fn();
        // // 相当于以下代码
         var num;

         function fn() {
             var num;
             console.log(num);
             num = 20;
             console.log(num);
         }
         num = 10;
         fn();
        // // 案例3
         var a = 18;
         f1();

         function f1() {
             var b = 9;
             console.log(a);
             console.log(b);
             var a = '123';
         }
        // 相当于以下代码
         var a;

         function f1() {
             var b;
             var a;
             b = 9;
             console.log(a);
             console.log(b);
             a = '123';
         }
         a = 18;
         f1();
        // 案例4
        f1();
        console.log(c);
        console.log(b);
        console.log(a);

        function f1() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        // 以下代码
         function f1() {
             var a;
             a = b = c = 9;
             // 相当于 var  a  = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看
             // 集体声明  var a = 9, b = 9, c = 9;
             console.log(a);
             console.log(b);
             console.log(c);
         }
         f1();
         console.log(c);
         console.log(b);
         console.log(a);

三、ES6新特性

1. let和const关键字

区别:let表示声明变量,而const表示声明常量,两者都为块级作用域;const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了。

需要注意:

  • let 关键词声明的变量不具备变量提升(hoisting)特性

  • let 和 const 声明只在最靠近的一个块中(花括号内)有效

  • 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING

  • const 在声明时必须被赋值

2. 原型和原型链

一般情况下,我们的公共属性定义到构造函数里面, 公共的方法我们放到原型对象身上 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数

3. 模板字符串

基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;ES6反引号 `` 直接搞定;

$("body").html(`This demonstrates the output of HTML content to the page, 
including student's ${name}, ${seatNumber}, ${sex} and so on.`);0

4. 扩展运算符

  • 扩展运算符可以将数组拆分成以逗号分隔的参数序列
let ary = ["a", "b", "c"];
console.log(...ary)//a,b,c
  • 扩展运算符应用于数组合并
    let ary1 = [1, 2, 3];
    let ary2 = [4, 5, 6];
    let ary3 = [...ary1, ...ary2];
    console.log(ary3)// [1, 2, 3, 4, 5, 6]

合并数组的第二种方法		
let ary1 = [1, 2, 3];
let ary2 = [4, 5, 6];
ary1.push(...ary2);
console.log(ary1)// [1, 2, 3, 4, 5, 6]
  • 利用扩展运算符将伪数组转换为真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs)
var ary = [...oDivs];
ary.push('a');
console.log(ary);

5. 箭头函数

  • 不需要 function 关键字来创建函数
  • 省略 return 关键字
  • 继承当前上下文的 this 关键字

6. 解构赋值

按照一定模式从数组或对象中提取值,然后对变量进行赋值(先提取,再赋值)

// 对象
const student = {
    name: 'Sam',
    age: 22,
    sex: '男'
}
// 数组
// const student = ['Sam', 22, '男'];

// ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex);

// ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);

7. Symbol

唯一标识,symbol作为对象的属性名时不会被for...in,for...of,Object.keys()识别;可以改用Reflect.ownkeys方法.

8. Promise

是一部编程的解决方案,状态不受外界影响

const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
}).then(res => {})
.catch(err => {})

9.Class类

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}

其中:

  1. constructor方法是类的默认方法,通过new 命令生成对象时会调用该方法,如果声明类时没有定义constructor,会默认定义一个空的。
  2. 生成实例时必须用new ,不用会报错
  3. 不存在变里提升(选定义类,再new实例)

类的静态方法:

所有在类中定义的方法都会被实例继承,如果不想被继承,可以在定义时加上static。表示为静态方法。

class Foo {
static match() {}
}
Foo.match()
const f = new Foo()
f.match() // 报错

类的实例属性

类的方法默认被实例继承,那么属性呢?也是继承的,写法如下:

class Foo {
myProp = 111;
...
}

classr的继承 extends

class Point {}
class PointSon extends Point {
constructor(x, y, z) {
super(x, y)
this.z = z
}
}

其中:

  1. super等同于父类的constructor。
  2. 子类必须在constructor中调用super, 也就是说用extends去继承一个类,就必须调用这个类(父类)的constructor。是因为子类没有自己的this对象,而是继承父类的this,然后对其进行加工
  3. 如果了类没有写constructor,会默认生成一个,并包含了super(...args)

5. new关键字

5.1 new关键字执行过程

    1. new 构造函数可以在内存中创建了一个空的对象 
    2. this 就会指向刚才创建的空对象
    3. 执行构造函数里面的代码 给这个空对象添加属性和方法
    4. 返回这个对象

后续更新中....