• JavaScript重点知识总结一


    感兴趣的朋友可以去我的语雀平台进行查看更多的知识。
    https://www.yuque.com/ambition-bcpii/muziteng

    1. 基础

    1.1 变量关键字

    JavaScript使用专门的关键字letvar来声明(定义)变量,在使用时需要注意一些细节

    let注意事项

    • 不允许重复声明
    • 只能在块级作用域内使用
    • 不存在变量提升,必须声明变量之后才能使用,不然会报Uncaught ReferenceError错误
    • JavaScript中内置的一些关键字不能被当做变量名

    var注意事项

    • 允许重复声明
    • 可以在任意位置使用
    • 可以在声明语句之前使用

    大部分情况使用letvar区别不大,但是let相较var更严谨,因此推荐使用let

    1.2 数据类型

    特点

    • js是弱类型动态语言,只有程序运行过程中才能确定类型
    • 变量的数据类型是可以变化的
    • 注:JavaScript中变量的值决定了变量的数据类型。

    数据类型的分类

    • 简单数据类型(Number String Boolean Undefined Null)
    • 复杂数据类型(Object)
    1.2.1 简单数据类型
    简单数据类型说明默认值
    Number数字型,整数或浮点数0
    Boolean布尔值true falsefalse
    String字符串“”
    Undefined变量只实名还没有赋值undefined
    Null空值null
    bigint是一种数字类型的数据,它可以表示任意精度格式的整数
    symbol

    数字型:即我们数学中学习到的数字,可以是整数、小数、正数、负数

    • 最大值Number.MAX_VALUE,比最大值大就是无穷大Infinty

    • 最小值 Number.MIN_VALUE,比最小值小就是无穷大-Infinty

    • 非数字 NaN isNaN()判断是否非数字

    • undefined和数字相加最后的结果是NaN

    1.2.2 数据类型转换

    转换为字符串

    image-20220911185206754

    转换为数字型(重点)

    image-20220911185347495

    转换为布尔型

    image-20220911185545734

    1.2.3 instanceof

    instanceof(判断实例方法)

    • 专门判断对象的具体类型
    • instanceof 运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链
    var b1 = {
    b2: [1, 'abc', console.log],
    //可以简化成 b3:()=>()=> 'hongjilin'  -->高阶函数相关知识
    b3: function () {
    return  () =>{  return   'hongjilin'}
    }
    }
    /**使用instanceof进行对象判断*/
    console.log(b1 instanceof Object, b1 instanceof Array) // true  false
    console.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true true
    console.log(b1.b3 instanceof Function, b1.b3 instanceof Object) // true true
    /**使用typeof进行对象中某属性的判断*/
    console.log(typeof b1.b2, typeof null) // 'object' 'object'
    console.log(typeof b1.b3='function') // true
    console.log(typeof b1.b2[2]='function') //true
    /**调用对象与数组中某函数示例*/
    b1.b2[2]('调用console.log打印hongjilin')    //调用console.log打印hongjilin
    console.log(b1.b3()()) // hongjilin
    

    1.3 函数

    函数形参和实参个数不匹配问题

    image-20220911190208699

    arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。

    1.4 作用域与内置对象

    1.4.1 作用域

    只要是代码,就至少有一个作用域,写在函数内部的局部作用域,如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域

    根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作用域链,作用域链就是采取就近

    原则的方式来查找变量最终的值。

    function f1() {
        var num = 123;
        function f2() {
            console.log( num );
        }
        f2();
    }
    var num = 456;
    f1();
    

    image-20220911190800297

    1.4.2 内置对象

    JavaScript中的对象分为3种

    • 自定义对象,属于 ECMAScript
    • 内置对象,属于 ECMAScript
    • 浏览器对象,属于JS独有

    内置对象:指JS语言自带的一些对象,供开发者使用,提供了一些常用的最基本而必要的功能(属性和方法)

    • 内置对象最大的优点就是帮助我们快速开发
    • JavaScript提供了多个内置对象:MathDateArrayString

    文档:MDN

    1.4.2.1 Math对象
    Math.PI				// 圆周率
    Math.floor()	// 向下取整
    Math.ceil()		// 向上取整
    Math.round()	// 四舍五入版 就近取整   注意 -3.5   结果是  -3 
    Math.abs()		// 绝对值
    Math.max()
    Math.min()		// 求最大和最小值 
    Math.random()	// 随机数方法,返回一个随机的小数  0 =< x < 1
    
    1.4.2.2 Date对象

    Date实例用来处理日期和时间。

    Date对象和Math对象不一样,他是一个构造函数,所以我们需要实例化后才能使用

    let date = new Date();
    console.log(date);  // Sun Sep 11 2022 19:17:01 GMT+0800 (中国标准时间)
    

    image-20220911191948787

    获取日期的总的毫秒形式

    Date对象是基于1970年1月1日(世界标准时间)起的毫秒数,常利用总的毫秒数来计算时间,因为它更精确

    valueOf() getTime() new Date() Date.now()获得距离1970年1月1号过了多少毫秒数

    1.4.2.3 数组对象

    数组对象的创建

    • 字面量方式 []

    • new Array([length]) new Array(...元素)

    检测是否为数组

    • instanceof运算符,可以判断一个对象是否属于某种类型
    • Array.isArray() 用于判断一个对象是否为数组,isArray()HTML5中提供的方法

    添加删除数组元素的方法

    image-20220911192329392

    image-20220911192342793

    注意:sort()默认按照比较字符串大小的方式一个字符一个字符的比,数字也是,除非传入一个方法

    image-20220911192432556

    image-20220911192503347

    image-20220911192515084

    slice(start, end)

    • start可以为负数,表示从数组尾部开始算起的位置。-1指最后一个元素,-2指倒数第二个元素,以此类推
    • end如果没有被指定,表示到最后。若指定,表示左闭右开 [start,end)
    • 方法不会修改数组本身,而是返回一个新数组

    splice(start[, deleteCount[, item1[, item2[, ...]]]])

    • start表示从什么位置开始添加或删除数组元素
    • deleteCount表示删除的元素数量,如果为0,则表示不删除数组元素
    • item1[, item2[, ...]]]] 表示新增的数组元素
    • 方法会改变原始数组
    let arr1 = [13, 4, 77, 1, 7];
    arr1.sort((a, b) => a - b); // 升序
    console.log(arr1)
    arr1.sort((a, b) => b - a); // 降序
    console.log(arr1)
    console.log(arr1.join())    // 默认为,
    
    let numbers = arr1.slice(1, 4); // 4,77,1 [begin,end) 左闭右开
    console.log(numbers)
    arr1.splice(1, 3);  // [13,7]
    console.log(arr1)
    
    1.4.2.4 字符串对象

    字符串的不可变

    指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

    image-20220911194717529

    image-20220911194725048

    image-20220911194741119

    replace(被替换的字符串, 替换为的字符串) 用于在字符串中用一些字符替换另一些字符,只替换第一个

    split()用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。

    toUpperCase()转换大写

    toLowerCase()转换小写

    includes()方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false

    2. 进阶

    2.1 函数

    2.1.1 回调函数
    • 你定义的
    • 你没有调
    • 但最终它执行了(在某个时刻或某个条件下)

    常见的回调函数

    • dom事件回调函数 ==> 发生事件的dom元素
    • 定时器回调函数 ===> window
    • ajax请求回调函数
    • 生命周期回调函数
    // dom事件回调函数
    document.getElementById("btn").onclick = function () {
        alert(this.innerHTML);
    }
    // 定时器回调函数
    setTimeout(function () {
        alert("到点了" + this)
    }, 2000);
    
    2.1.2 函数中的this

    this

    • 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
    • 所有函数内部都有一个变量 this
    • 它的值是调用函数的当前对象

    如何确定this的值?

    • test() window
    • p.test() p
    • new test() 新创建的对象
    • p.call(obj) obj
    function Person(color) {
        console.log(this);
        this.color = color;
        this.getColor = function () {
            console.log(this)
            return this.color;
        }
        this.setColor = function (color) {
            console.log(this)
            this.color = color;
        }
    }
    
    const obj = {};
    Person("red");  //this是谁? window
    
    const p = new Person("yello");  //this是谁?p
    p.getColor();
    
    // 调用call会改变this指向--->让我的p函数称为obj的临时方法及逆行调用
    p.setColor.call(obj, "black");  //this是谁?obj
    
    const test = p.setColor;
    test(); //this是谁?window
    
    2.1.3 原型与原型链
    2.1.3.1 原型prototype

    函数的prototype属性

    • 每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为原型对象

    • 原型对象中有一个属性constructor,它指向函数对象

    image-20220911233818444

    给原型对象添加属性(一般都是方法)

    • 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
    // 每个函数都有一个prototype属性,它默认指向一个Object空对象(原型对象)
    console.log(Date.prototype, typeof Date.prototype);
    
    function Fun() {
    }
    
    console.log(Fun.prototype)  // 默认指向一个Object空对象(没有自己的属性)
    
    // 原型对象中有一个属性constructor,它指向函数对象
    console.log(Date.prototype.constructor === Date)    // true
    console.log(Fun.prototype.constructor === Fun)      // true
    
    // 给原型对象添加属性、方法(一般是方法) ===> 实例对象可以访问
    Fun.prototype.test = function () {
        console.log("test()")
    }
    
    let fun = new Fun();
    fun.test();
    

    image-20220911234514487

    2.1.3.2 显示原型与隐式原型
    1. 每个函数function都有一个prototype,即显式原型属性
    2. 每个实例对象都有一个__proto__,可称为隐式原型属性
    3. 对象的隐式原型的值为其对应构造函数的显式原型的值
    // 定义构造函数
    function Fn() {
        // 内部默认执行语句:this.prototype = {}
    }
    
    // 1.每个函数function都有一个prototype,即显示原型属性,默认指向一个空的Object对象
    console.log(Fn.prototype)
    
    // 创建实例对象
    let fn = new Fn() // 内部默认执行语句:this.__proto__ = Fn.prototype
    // 2.每个实例对象都有一个__proto__,可称为隐式原型
    console.log(fn.__proto__)
    
    // 3.对象的隐式原型的值为其对应构造函数的显示原型的值
    console.log(Fn.prototype === fn.__proto__)    // true
    
    // 给原型添加方法
    Fn.prototype.test = function () {
        console.log("test()")
    }
    
    // 通过实例对象调用原型方法
    fn.test();	// test()
    

    内存结构

    image-20220911235250668

    总结

    • 函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object实例对象(Object 函数除外,因为__proto__ 属性为

      null)

    • 对象的__proto__ 属性:创建对象时自动添加的,默认值为构造函数的prototype属性值,Function函数

    • 程序员可以直接操作显式原型,但不能直接操作隐式原型(ES6之前)

    2.1.3.3 原型链

    原型链

    访问一个对象的属性

    • 先在自身属性中查找,找到返回
    • 如果没有, 再沿着__proto__这条链向上查找,找到返回
    • 如果最终没找到,返回undefined

    image-20220911235659250

    • 别名:隐式原型链
    • 作用:查找对象的属性(方法)

    构造函数/原型/实例对象的关系(图解)

    var o1 = new Object();
    var o2 = {};
    

    image-20220912000049248

    所有函数的__proto__都是一样的

    • 函数现实原型默认值是一个空Object实例对象(Object 函数除外,因为__ proto __ 属性为 null)
    • 所有函数都是Function函数的实例,包括Function本身
    • Object的原型对象是原型链的尽头Object.prototype.__proto__为 null

    image-20220912000224315

    属性问题

    读取对象的属性值时:会自动到原型链中查找

    设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值

    方法一般定义在原型中,属性一般通过构造函数定义在对象本身上

    2.1.4 闭包

    返回函数的函数[高阶函数]

    let val = 7
    function createAdder() {
      function addNumbers(a, b) {
        let ret = a + b
        return ret
      }
      return addNumbers
    }
    let adder = createAdder()
    let sum = adder(val, 8)
    console.log('example of function returning a function: ', sum)
    

    高阶函数:就是一个函数就可以接收另一个函数作为参数,或者是返回一个函数–>常见的高阶函数有map、reduce、filter、sort等

    let add = function add(a) {
        return function (b) {
            return a + b;
        }
    }
    console.log(add(2)(3)); //5
    

    map

    // map接受一个函数作为参数,不改变原来的数组,返回一个全新的数组
    let arr = [1, 2, 3, 4, 5];
    let arr2 = arr.map(item => item * 2);
    console.log(arr2)   // [2,4,6,8,10]
    

    reduce

    let arr = [1, 2, 3, 4, 5];
    // reduce接受一个函数作为参数,这个函数要有两个形参,代表数组中的前两项
    // reduce会将这个函数的结果与数组中的第三项再次组成这个函数的两个形参以此类推进行累计操作
    let arr3 = arr.reduce((a, b) => a + b);
    console.log(arr3); // 15
    

    filter

    let arr = [1, 2, 3, 4, 5];
    // filter返回过滤后的数组。filter也接受一个函数作为参数,这个函数作用于数组中的每个元素
    // 根据该函数每次执行后返回的布尔值来保留结果,如果是true就保留,如果是false就过滤掉
    let arr4 = arr.filter(item => item % 2 === 0);
    console.log(arr4);  // [2,4]
    

    …TODO

    2.2 面向对象

    2.2.1 继承模式
    2.2.1.1 原型链继承
    1. 套路
      1. 定义父类型构造函数
      2. 给父类型的原型添加方法
      3. 定义子类型的构造函数
      4. 创建父类型的实例对象赋值给子类型的原型
      5. 将子类型原型的构造属性设置为子类型
      6. 给子类型原型添加方法
      7. 创建子类型的对象,可以调用父类型的方法
    2. 关键
      1. 子类型的原型为父类型的一个实例对象
    // 父类型
    function Supper() {
      this.supProp = '父亲的原型链'
    }
    // 给父类型的原型上增加一个 showSupperProp 方法,打印自身 subProp
    Supper.prototype.showSupperProp = function () {
      console.log(this.supProp)
    }
    
    // 子类型
    function Sub() {
      this.subProp = '儿子的原型链'
    }
    // 子类型的原型为父类型的一个实例对象
    Sub.prototype = new Supper()
    // 让子类型的原型的constructor指向子类型
    // 如果不加,其构造函数找的[`new Supper()`]时从顶层Object继承来的构造函数,指向[`Supper()`]
    Sub.prototype.constructor = Sub
    // 给子类型的原型上增加一个 showSubProp 方法,打印自身 subProp
    Sub.prototype.showSubProp = function () {
      console.log(this.subProp)
    }
    
    var sub = new Sub()
    
    sub.showSupperProp() // 父亲的原型链
    sub.showSubProp() // 儿子的原型链
    console.log(sub)  
    /**
      Sub {subProp: "儿子的原型链"}
      subProp: "儿子的原型链"
      __proto__: Supper
      constructor: ƒ Sub()
      showSubProp: ƒ ()
      supProp: "父亲的原型链"
    	__proto__: Object
    */
    

    示例图

    注意:此图中没有体现 constructor 构造函数,会在下方构造函数补充处指出

    image-20220912002946860

    Sub.prototype.constructor = Sub 如果不加,会指向 Supper

    2.2.1.2 借用构造函数继承(假的)

    套路

    • 定义父类型构造函数
    • 定义子类型构造函数
    • 在子类型构造函数中调用父类型构造

    关键

    • 在子类型构造函数中通用call()调用父类型构造函数

    作用

    • 能借用父类中的构造方法,但是不灵活
    function Person(name, age) {
      this.name = name
      this.age = age
    }
    function Student(name, age, price) {
      // 此处利用call(),将 [Student]的this传递给Person构造函数
      Person.call(this, name, age)  // 相当于: this.Person(name, age)
      /*this.name = name
     this.age = age*/
      this.price = price
    }
    
    var s = new Student('Tom', 20, 14000)
    console.log(s.name, s.age, s.price)
    

    Person中的this是动态变化的,在[Student]中利用[Person.call(this, name, age)]改变了其this指向,所以可以实现此效果

    2.2.1.3 组合继承

    原型链 + 借用构造函数的组合继承

    • 利用原型链实现对父类型对象的方法继承
    • 利用super()借用父类型构建函数初始化相同属性
    function Person(name, age) {
      this.name = name
      this.age = age
    }
    Person.prototype.setName = function (name) {
      this.name = name
    }
    
    function Student(name, age, price) {
      Person.call(this, name, age)  // 为了得到属性
      this.price = price
    }
    Student.prototype = new Person() // 为了能看到父类型的方法
    Student.prototype.constructor = Student // 修正constructor属性
    Student.prototype.setPrice = function (price) {
      this.price = price
    }
    
    var s = new Student('Tom', 24, 15000)
    s.setName('Bob')
    s.setPrice(16000)
    console.log(s.name, s.age, s.price)
    
  • 相关阅读:
    【软考】6.2 网络安全技术
    数据沿袭是止痛药还是维生素?
    数据结构-b树
    电脑上使用的备忘记事软件哪一款好用点?
    大规模 IoT 边缘容器集群管理的几种架构-4-Kubeedge
    银行有没有必要建立数据中台?看完你就明白了
    Zookeeper学习一
    算法---树状数组
    2016年上半年上午易错题(软件设计师考试)
    Escape character is ‘^]’什么意思?怎么使用telnet
  • 原文地址:https://blog.csdn.net/m0_52781902/article/details/126944463