JavaScript基础入门

147 阅读5分钟

“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情

​JS基础

💬初识JS

js介绍

是前端唯一的脚本语言(脚本:不需要编译,直接通过引擎运行)

  1. 通常运行在浏览器中的编程语言

  2. 作用

    1. 监听用户行为,并作出反馈
    2. 网页特效(动画效果)
    3. 表单验证(针对表单数据的合法性进行判断)
    4. 数据交互(获取后台数据,渲染到页面)
    5. 服务端编程(node.js)

js组成

  1. ECMAScript规范

    • 规定了js基础语法核心知识
  2. Web APIs(可操作的实体对象)

    • DOM

      • 操作文档,比如对页面元素进行移动、大小、添加删除等操作
    • BOM

      • 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等

js引入方式

  1. 注意点

    1. script 必须写在body 结束标签最后面

    2. 外部js 内部写代码会被忽略

    3. 内部js 要写在body结束标签前面

  2. 行内式的js

  3. 内嵌式js

    • 内部js 要写在body结束标签前面
  4. 外部js

    • 外部js内部写代码会被忽略

✅JS输入输出语句

  • document.write()

    • 追加到 body结束标签之前

      • 原理拼接文档流
      • 文档闭合才会被解析
    • 会解析 html 标签

    • 影响布局(调试时不用)

  • 输入

    • prompt('')

      • console.log(prompt('type num')); // 控制台输出用户输入的信息
      • 阻塞文档的解析
      • prompt用户输入的值是 字符串
  • 弹出警示框

    • alert('')
    • 阻塞文档的解析
  • 控制台输出

    • console.log('') 程序员测试用的
    • 输出多个 用逗号分隔
    • ctrl+shift+l(javascript console utils)

✅字面量

  • 在计算机科学中,字面量(literal)是在计算机中描述事/物 数据 类型

    • 123 是数字字面量
    • '黑马程序员' 字符串字面量
    • [] 数组字面量

✅变量

变量的本质

  • 变量:内存中申请的一块用来存放数据的小空间

  • 特点

    • 最好要声明 并给出值

      • 变量声明会提升(暂时性死区),let age(age变量指向这个地址)
      • age= 19;访问age这个地址,找到这个空间,再往空间里存值18.
      • var 没有声明之前也可使用
    • js 有很强的逻辑性:实现的思路 先怎么做后怎么做(a = b; b = c, c=a 交换bc)

  • 📄 关键字

    • let

      1. 允许声明和赋值同时进行

      2. 不允许重复声明

        • 修改:重新赋值
      3. 允许同时声明多个变量并赋值

        • let name = 'wendy',age = 19;
      4. JavaScript 中内置的一些关键字不能被当做变量名

    • ✖️var(不使用)

      1. 允许声明和赋值同时进行
      2. 允许重复声明
      3. 允许同时声明多个变量并赋值
    • let 相较 var 更严谨,因此推荐使用 let

  • 变量名命名规则

    1. 由字母、数字、下划线、$符号组成,不能以数字开头
    2. JavaScript 内已占用于单词(关键字或保留字)不允许使用
    3. 尽量保证变量具有一定的语义,见字知义,遵守小驼峰式命名法
  • 年龄计算案例
    •  // 思路
       // 1. prompt--》2. 保存年份 今年年份- 年份 3. alert
           var year = prompt('请您输入您的出生年份');
           var age = 2018 - year; //year 取过来是字符串型 但是用的减法 有隐式转换
           alert('您今年已经'+ age +'岁了')
      
  • 💬ATM取款机案例
    1. 不断的弹出对话框

    2. 除非输入的是4 则退出循环 break

       if (str === '4') {
                       break;
                   }
      
    3. 金额的变量

    4. switch() 加减操作

比较运算符

  • 介绍

    • 比较两个数的大小是否相等
  • 特点

    • == 等于: 只比较 的大小

      • 所有类型都会转化成数字的大小
    • === 全等: 比较 值的大小 和 类型

    • != 不等于:

    • !== 不全等:

  • 字符串的比较

    • NaN 不等于任何值;包括自身 永远等于 false 要判断一个数是否为 NaN用 isNaN()

    • '2' > '19' // true 先比较第一个

    • 比较小数

      • 尽量不要比较(计算)小数; 小数有精度问题
      • 小数在内存中存储方式,会导致精度问题
      • 前端进行计算的时候,使用 计算函数库(别人帮我们写好了的一系列,用于计算的方法)
  • 逻辑运算符

    • 应用场景

      • 数据做判断
    • 简写代码--短路运算

    • && 逻辑与

      • 一假则假
      • 1 && 4 // 4
    • || 逻辑非

      • 一真则真
    • 短路运算符

      • 只要 && 左边为false,右边就被短路
      • 只要 || 左边为true,右边就会短路
      • 短路表达式:有返回值
      •  let num;
         let age = num || 12; // 12 默认值的赋值(这里没有默认值)
         let num1 = 11;
         let num2 = num1 || 12 // num2 = 11 默认值赋值
        
  • 运算符优先级

    • 先计算,再比较大小,后判断相等,最后判断逻辑运算符
    • 逻辑与 优先级高于 逻辑非
    • 多用()

✅数组

  • 创建数组

    1. 利用 new 创建数组

       var arr = new Array();
        var arr2 = new Array(2); // 创建了一个长度为 2 的含有 2 个空的数组元素
        var arr3 = new Array(2, 3); // 等价于 [2, 3] 表示里面有两个数组元素 分别是 2 3
      
    2. 利用数组字面量创建数组 []

        var arr1 = [1, 2, 'teacher', true]; // 数组可以存放任意类型数据
      
  • 数组转变为字符串

    •  var str += arr[i];
      
    • 数组长度是动态变化的
  • 添加删除数组元素的方法

    1. push()

      • (1) 在数组 末尾 添加个或个数组元素
      • (2) 参数直接写数组元素就可以了
      • (3) push 完毕之后返回结果是数组长度
      • (4) 原数组也会发生变化
      • (5) 应用:筛选数组
    2. unshift()

      • (1) 在数组 开头 提那家一个或多个数组元素
      • (2) 参数直接写数组元素就可以了
      • (3) unshift完毕之后返回结果是数组长度
      • (4) 原数组也会发生变化
       arr.push(4, 'pink');
      
    3. splice()

      1. 删除任意位置的元素

      2. 可以用来删除多个元素

      3. 返回值为,被删除的元素数组

      4. ❗️ 注意

        1. 被删除的元素包含了开始值
        2. 第二个参数不填的话,执行结果为删除起始值,到最后一个元素
        3. splice(起始位,要删除的数量,要替换成的元素)
  • 返回数组元素索引方法 indexOf(数组元素)

    • (1) 只返回第一个满足条件的索引号 从前开始查找

    • (2) 找不到 返回 -1 应用:数组去重

    • (3) lastIndexOf(数组元素) 最后一个满足条件的索引号 从后开始查找

    • 作用:

      • 删除元素:arr.splice(arr.indexOf(qs.innerHTML), 1)
  • 数组转化为字符串

    • (1) toString() 将我们的数组转换为字符串

    • (2) join(分隔符)

       console.log(arr6.join('-')); // '-' 连接
      

从数组中随机生成一个数

 let i = Math.floor(Math.random() * students.length);

清空数组小技巧

  • array.length = 0

⭐️数据类型

  • 通过 typeof 关键字检测数据类型

  • js 的变量数据类型是只有程序在运行过程中,根据等号右边的值来确定的 var js是动态语言 数据类型可以变化(更新)

    1. 简单数据类型

      • 值类型:string number boolean undefined null 存放在 栈 里面

      • null

        • 返回的是一个空的对象
        • object 如果有变量以后打算存储为对象 暂时没想好放啥 这时候就给 null
      • number

        • 0 开头会被识别为 八进制
      • string

        • ``

          • 用来拼接字符 ${}
          • 中间可以使用 回车
      • undefined

        • 在某个时候,想知道,数据到底传给我们没有,可以判断一下,data变量(为了存储后端返回的数据)是否等于 undefined
    2. 复杂数据类型

      • 引用类型:通过 new 创建对象 Object Array Date 存放在 堆 里面
      • 首先在栈里面存放十六进制表示的地址 然后地址指向堆里的数据

  • 数据类型传参

    • (1) 简单数据类型传参是传结果 原本值不变
    • (2) 复杂数据类型传参是传地址 原本值改变

⭐️数据类型转换

  1. 转化为字符型

    1. 把数字型转换为字符串型 toString()

       var str = num.toString();
      
    2. 利用 String(变量)

       console.log(String(num));
      
    3. 利用 + 拼接字符串的方法实现转换效果 隐式转换

       console.log(num + '');
      
  2. 转换为数字型

    1. parseInt(变量) 可以把字符型的转换为数字型 得到的是整数 过滤单位

      • 不会四舍五入
      • 第一个字不为数字类型时返回NaN,否则,除去后面
       console.log(parseInt('3.14')); // 3取整
       console.log(parseInt('3.94')); // 3取整
       console.log(parseInt('120px')); // 120 去单位
       console.log(parseInt('rem120px')); //NaN
      
  3. parseFloat(变量) 可以把 字符型的转换为数字型 得到的是小数 浮点数

    • parseFloat("123abc") // 123

      • parseInt和parseFloat(parse解析的意思),若是数字开头的字符串,返回的数字为NaN,第一个数字直到遇到非数字字符,之间的纯数字;

    1. 利用Number(变量)

      • 当数据不能转化为数字的时候,会返回 NaN

      • NaN 是一个数字类型

        • NaN不等于任何值,包括本身
    2. 利用了算数运算 - * / == != > <隐式转换

       console.log('12'-0); // 12
               console.log('123'-'120');
      
      • 除了加号(+)之外,算术运算符:会把数据类型转化为数字类型

注意 ❗️:

  • 如果两边都是数值(Number)类型 则是+号运算符

  • +号

    • 数字相加

      • 只有一个字符串 eg:+prompt('type num:')
    • 字符相连

      • 左右如果有 一个 数据是字符串数据类型的话 那么这个+号会被解析成连接符
  • prompt用户输入的值是 字符串

  • 取余

    • 开发用法:

      • 判断某个数字是否能被整除
      • 判断 奇偶:% 2 奇 = 1 偶 = 0

💬字符串操作方法

  1. concat('字符串 1','字符串 2'...)

  2. substr('截取起始索引位置','截取几个字符');

  3. 替换字符 replace('被替换的字符','替换为的字符') 只会替换一个字符

    • 替换多个字符

       var str2 = 'anjaohquoao';
       while (str2.indexOf('o') !== -1) {
           // str2.replace('o', '*');
           str2 = str2.replace('o', '*');
       }
      
  4. 字符转换为数组 split('分隔符')

     var str3 = 'red, blue, white';
     console.log(str3.split(','));
    

⭐️循环

  • switch...case

    • 处理 case 为比较确定值的情况

    • 分支较多时,执行效率较高

    • 是===比较 对成绩除10, 取整, 和9, 8, 7, 6判断

       let num = 1;
         switch (num) {
           case 1: // 相当于 if(num === 1) 【注意是全等】
             console.log("你的num===1");
             break; // 如果不写break; 程序会继续往下运行,去检查其他case是否符合条件;
           case 2: // 相当于 if(num === 2 || num === "2")
           case "2":
             console.log("你的num===2");
             break;
           default: // 相当于 esle
             console.log("不满足以上所有的case,会执行default");
             break;
         }
      
  • if else if(主流)

    • 更加灵活,常用于范围判断(大于、小于、等于某个范围)
    • 分支少时,执行效率高
  • for循环

    • 可以重复执行些许不同的代码,用计时器
    • for 循环是循环条件和数字相关的循环
  • 双重 for 循环

    • 外层循环一次,内层循环执行全部
  • while

    • 用while(true) 一直循环或者 while(条件)
    • 可能一次也不执行
  • do while

    • 至少执行一次循环体

⭐️预解析

  • js 引擎运行:

    1. 预解析

      • 把所有的 var function 提升到当前作用域的最前面

      • 变量提升

        • 把所有变量的声明 提升到当前作用域最前面 不提升赋值
    2. 代码执行

      • 按代码书写顺序从上往下执行
       // 案例 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;
             //     a = '123';
             //     console.log(a);
             //     console.log(b);
             // }
             // a = 18;
             // f1();
     ​
      var a = b = c = 9;
      // 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有 var 声明 当全局变量看
    

⭐️JS作用域

  • 局部作用域(函数作用域)只能在函数内部使用

  • 执行效率:

    (1)全局变量 只有浏览器关闭才会销毁,比较占用资源

    (2)局部变量 当程序执行完毕就会销毁,比较节约资源

  • 块级作用域

    • 所有{}都会形成独立的块级作用域,例如if、for,注意对象的{}不包括在内。
    • {} if{} for{} es6 新增块级作用域
    • let 具有块级作用域

    • 局部里面没有声明 b,执行顺序是 b = 20,所以向上找 b 的声明
    • 变量未声明,局部直接赋值,当全局变量看
  • 作用域链
     // 作用域链 采取链式查找 层层递进 (由内往外找)
         var num = 10;
     ​
         function fn() { //外部函数
             var num = 20;
     ​
             function fun() { //内部函数
                 console.log(num); //20
             }
             fun();
         }
         fn();
    

作用域特殊情况

  • for 循环,声明初始值的变量,也块级变量
  • 函数形参,是一个 局部变量
  • 在块级或局部,未声明变量,直接赋值变量,相对于创建了一个全局变量

⭐️函数

  • 实参 > 形参个数 取到形参个数 < undefined

  • return 只能返回一个值,返回的结果是最后一个值,如果要返回多值则返回一个数组,return 后面的不会执行

    • 函数没写 return 默认返回 undefined
  • arguments 存储了所有传递过来的实参 伪数组

    •  function fn() {
               console.log(arguments);
           }
       fn(1, 2, 3);
      
  • 函数的声明方式

    •  // 1.利用函数关键字自定义函数(命名函数)
          function fn() { };
      
    •  // 2.函数表达式
         var 变量名 = function () {};
      

匿名函数

  • 作为值传递

  • 作为实参传递

  • ❗️ 两个匿名函数之间,要加上 ;

  • eg:

     (function (val) {
             liList[val].addEventListener('click', function () {
                 console.log(val);
             })
         })(i) // 调用函数 并传入参数 i  闭包
    

立即执行函数

  • 作用:解决命名冲突,避免了全局变量之间的污染
  • ❗️一定记得 不同的立即执行函数间加上 ';'

关注点

  • 函数的作用
  • 函数的参数
  • 函数的返回值

⭐️对象

  • 释义

    • js 对象:所有具体的事物 属性(特征)与方法(行为)的集合
  • 创建对象的方法

    1. 利用对象字面量创建对象

      • var obj = {};
      •  var obj = {
             userName: 'wendy',
             age: 18,
             sex: 'man',
             sayHi: function () {
                 console.log('hi~');
             } //方法后面跟的是匿名函数
         }
        
    2. 利用 new Object 创建对象

      •  var obj = new Object();
         obj.userName = 'wendy',
         obj.age = 18,
         obj.sex = 'man',
         obj.sayHi = function () {
             console.log('hi~');
         }
         console.log(obj.age);
         obj.sayHi();
        
  • 调用属性的两种方法

    1. 对象名.属性名

       console.log(obj.age);
      
    2. 对象名 ['属性名']

       console.log(obj['sex']);
      
  • 删除对象

    • delete 方法

      • delete obj.a; // 返回 true
      • 属性名不存在也会返回 true
      • 所以不能靠返回值判断是否删除成功,用 if(obj.a !=undefined)
      • 删除无法被删除的属性时才会返回 false

js获取对象的长度

  • 对象的长度不能用.length获取,用js原生的Object.keys可以获取到
 var obj = {'name' : 'Tom' , 'sex' : 'male' , 'age' : '14'}; 
 ​
 var arr = Object.keys(obj); 
 ​
 console.log(arr);  // ['name','sex','age'] 
 ​
 console.log(arr.length);  //3
 ​

⭐️构造函数

  • 利用构造函数创建对象,避免代码重复冗余

  • 格式:

    •  1. /* function 构造函数名 (值) {
             this.属性 = 值;
            this.方法 = function () {}
         }
         new 构造函数名 (); */
      
    • 调用构造函数

      • var wendy = new Star('wendy', 18, 'woman');
  • ❗️ 注意点

    1. 构造函数名字首字母要大写

    2. 构造函数不需要 return 就可以返回结果

    3. 属性或方法前面一定要用 this

    4. 调用构造函数一定要用 new

      • new 关键字的执行过程

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

    • forin 语法
     // for (变量 in 对象){}
     for (let k in obj) {
         console.log(k); // k/key 变量 输出的是 属性名
         console.log(obj[k]); // obj[k] 得到的是 属性值
         // 不能用 obj.k
     }
    
    • 先打印出数字类型的属性(排序,小到大),后字符串(俺书写顺序)

✅内置对象

⭐️Math对象

  1. 查看 MDN 文档

    • Math.random() [0,1) 随机小数

      • Math.random()*5+5 [5,10)
      • Math.floor(Math.random()*(max-min+1)+min [min,max])
      • Math.ceil(Math.random()) 只有随机小数为 0 时才为 0 概率小 不合适
      • 一般封装成 工具函数 使用
    • Math.max(1,3,4,2)

    • Math.min(1,3,4,2)

    • Math.abs() 绝对值

    • Math.ceil() 向上取整

    • Math,floor() 向下取整

    • Math.pow() 幂运算

  2. 利用对象 封装自己 的数学对象 里面有 PI 最大值 最小值

     var myMath = {
     PI: 3.1415,
     max: function (arguments) {
         var max = arguments[0];
         for (var i = 0; i < arguments.length; i++) {
             if (arguments[i] > max) {
                 max = arguments[i];
             }
         }
         return max;
     },
     ​
     min: function (arguments) {
         var min = arguments[0];
         for (var i = 0; i < arguments.length; i++) {
             if (arguments[i] < min) {
                 min = arguments[i];
             }
         }
         return min;
     }
     }
     console.log(myMath.PI);
     console.log(myMath.max([1, 2, 3, 99]));
     console.log(myMath.min([1, 4, 0, 66]));
    
  3. 绝对值方法

     console.log(Math.abs(-1));
     console.log(Math.abs('1')); // 隐式转换 会把字符型转换为数字型
     console.log(Math.abs('pink')); // NaN
    
  4. 三个取整方法

    • (1) Math.floor() 向下取整 往下的取

       console.log(Math.floor(1.1)); // 1
       console.log(Math.floor(1.9)); // 1
      
    • (2) Math.ceil() 往上取

    • (3) Math.round() 四舍五入 .5 特殊 往大了取

       console.log(Math.round(1.5)); // 2
       console.log(Math.round(-1.5)); // -1
       console.log(Math.round(-1.3)); // -1
      
  5. 随机数

    • Math.random() 0 ~ 1 的浮点数 不跟参数

    • 想要得到两个数之间的随机整数 并且包含这 2 个整数

      • Math.floor(Math.random() * (max - min + 1)) + min;
      •  function getRandom(min, max) {
         return Math.floor(Math.random() * (max - min + 1)) + min;
         }
         console.log(getRandom(1, 10));
        
  6. 随机点名

    •  var arr = ['wendy', 'ben', 'lisa', 'exo'];
       ​
       function getRandom(min, max) {
           return Math.floor(Math.random() * (max - min + 1)) + min;
       }
       console.log(arr[getRandom(0, arr.length - 1)]);
      

✅Date 日期对象

  • 是一个构造函数 必须使用 new 来调用创建我们的日期对象

    1. 使用 Date 如果没有参数 返回当前系统的当前时间

    2. 参数常用方法 数字型 2019, 10, 01 或者是 字符串型 '2019-10-01 8:8:8' h / m / s

      • 特殊

         var date1 = new Date(2019, 10, 01);
         console.log(date1); // 返回的是 11 月
        
    3. 日期格式化

       console.log(date.getFullYear()); // 返回当前日期的年
       console.log(date.getMonth() + 1); // 月份 返回的月份小 1 个月 记得月份 +1 哦
       console.log(date.getDay()); // 周日返回的是 0
       var day = date.getDay();
       var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
       console.log('今天是' + arr[day]);
      
    4. 格式化日期 时分秒

       function getTime() {
           var time = new Date();
           var h = time.getHours();
           h = h < 10 ? '0' + h : h;
           var m = time.getMinutes();
           m = m < 10 ? '0' + m : m;
           var s = time.getSeconds();
           s = s < 10 ? '0' + s : s;
           return h + ':' + m + ':' + s;
       }
      
    5. 获得 Date 总的毫秒数 (时间戳)

      • 不是当前时间的毫秒数 而是距离 1970-01-01 多了多少毫秒

      • 1.通过 valueOf() getTime()

         var date = new Date();
         console.log(date.valueOf());
         console.log(date.getTime());
        
      • 2.简单常用写法

      •  var date1 = +new Date(); // + new Date() 返回的就是总毫秒数
                 console.log(date1);
        
      • 3.H5 新增的 获得总的毫秒数

                 console.log(Date.now());
        
    6. 倒计时案例

      • 核心算法:输入时间 - 现在时间 但是时分秒不能直接相减

      • 用时间戳来做。输入总秒数 - 现在时间总秒数 = 剩余总秒数

      • 剩余时间转化为 天、时、分、秒

         function countDown(time) {
             var nowTime = +new Date();
             var inputTime = +new Date(time);
             var time = (inputTime - nowTime) / 1000; // 剩余时间秒数
         ​
             var day = parseInt(time / 60 / 60 / 24); //parseInt() 函数可解析一个字符串,并返回一个整数。
             day = day < 10 ? '0' + day : day;
         ​
             var hour = parseInt(time / 60 / 60 % 24);
             hour = hour < 10 ? '0' + hour : hour;
         ​
             var minute = parseInt(time / 60 % 60);
             minute = minute < 10 ? '0' + minute : minute;
         ​
             var seconds = parseInt(time % 60);
             seconds = seconds < 10 ? '0' + seconds : seconds;
         ​
             return day + '天' + hour + '时' + minute + '分' + seconds + '秒'
         }
         console.log(countDown('2022-3-10 09:00:00'));
         console.log(new Date());
        

📖杂记📄

  • prompt 过来的是字符串型

  • break 跳出所在循环(只是结束{}里函数运行,不能结束总函数)return 才是结束总函数,continue 退出本次循环并执行下一次循环

  •  var garde = +prompt('请输入学生成绩');
     // 注意没有‘+’之前 grade 是字符串型
    
  • 冒泡sort() 的完美写法

     var arr2 = [1, 13, 4, 7, 77];
     arr2.sort(function (a, b) {
         return a - b; //升序排列
         // return b -a; 降序排列
     });
    
  • 属性href指的是与 JavaScript 对象相关的值。JavaScript 对象是无序属性的集合。

  • forEach

    • 伪数组不能用,for in 伪数组可以用
    • 不能被 break 打断,array.forEach((item,index)=>{})
  • for in

    • 对象中使用

📖📖this指向问题

  1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)

  2. 方法调用中谁调用this指向谁

  3. 构造函数中this指向构造函数的实例

  4. bind、call、apply 修改 this 的指向

    1. call 和 apply 会在调用原函数的同时也修改 this 的指向

      • call 和 apply 的区别

        • 传递参数不同
        •  obj.say.call(newObj,1,2)
           obj.say.apply(newObj,[1,2])
          
    2. bind 会帮你修改 this 指向 但是不会直接调用 原函数 而是会返回一个 修改了 this 指向的新函数