“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情”
JS基础
💬初识JS
js介绍
是前端唯一的脚本语言(脚本:不需要编译,直接通过引擎运行)
-
通常运行在浏览器中的编程语言
-
作用
- 监听用户行为,并作出反馈
- 网页特效(动画效果)
- 表单验证(针对表单数据的合法性进行判断)
- 数据交互(获取后台数据,渲染到页面)
- 服务端编程(node.js)
js组成
-
ECMAScript规范
- 规定了js基础语法核心知识
-
Web APIs(可操作的实体对象)
-
DOM
- 操作文档,比如对页面元素进行移动、大小、添加删除等操作
-
BOM
- 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等
-
js引入方式
-
注意点
-
script 必须写在body 结束标签最后面
-
外部js 内部写代码会被忽略
-
内部js 要写在body结束标签前面
-
-
行内式的js
-
内嵌式js
- 内部js 要写在body结束标签前面
-
外部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-
允许声明和赋值同时进行
-
不允许重复声明
- 修改:重新赋值
-
允许同时声明多个变量并赋值
- let name = 'wendy',age = 19;
-
JavaScript 中内置的一些关键字不能被当做变量名
-
-
✖️
var(不使用)- 允许声明和赋值同时进行
- 允许重复声明
- 允许同时声明多个变量并赋值
-
let相较var更严谨,因此推荐使用let
-
-
变量名命名规则
- 由字母、数字、下划线、$符号组成,不能以数字开头
- JavaScript 内已占用于单词(关键字或保留字)不允许使用
- 尽量保证变量具有一定的语义,见字知义,遵守小驼峰式命名法
-
年龄计算案例
-
// 思路 // 1. prompt--》2. 保存年份 今年年份- 年份 3. alert var year = prompt('请您输入您的出生年份'); var age = 2018 - year; //year 取过来是字符串型 但是用的减法 有隐式转换 alert('您今年已经'+ age +'岁了')
-
-
💬ATM取款机案例
-
不断的弹出对话框
-
除非输入的是4 则退出循环
breakif (str === '4') { break; } -
金额的变量
-
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 默认值赋值
-
-
-
运算符优先级
- 先计算,再比较大小,后判断相等,最后判断逻辑运算符
- 逻辑与 优先级高于 逻辑非
- 多用()
✅数组
-
创建数组
-
利用 new 创建数组
var arr = new Array(); var arr2 = new Array(2); // 创建了一个长度为 2 的含有 2 个空的数组元素 var arr3 = new Array(2, 3); // 等价于 [2, 3] 表示里面有两个数组元素 分别是 2 3 -
利用数组字面量创建数组 []
var arr1 = [1, 2, 'teacher', true]; // 数组可以存放任意类型数据
-
-
数组转变为字符串
-
var str += arr[i]; - 数组长度是动态变化的
-
-
添加删除数组元素的方法
-
push()
- (1) 在数组 末尾 添加一个或多个数组元素
- (2) 参数直接写数组元素就可以了
- (3) push 完毕之后返回结果是数组长度
- (4) 原数组也会发生变化
- (5) 应用:筛选数组
-
unshift()
- (1) 在数组 开头 提那家一个或多个数组元素
- (2) 参数直接写数组元素就可以了
- (3) unshift完毕之后返回结果是数组长度
- (4) 原数组也会发生变化
arr.push(4, 'pink'); -
splice()
-
删除任意位置的元素
-
可以用来删除多个元素
-
返回值为,被删除的元素数组
-
❗️ 注意
- 被删除的元素包含了开始值
- 第二个参数不填的话,执行结果为删除起始值,到最后一个元素
- 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是动态语言 数据类型可以变化(更新)
-
简单数据类型
-
值类型:string number boolean undefined null 存放在 栈 里面
-
null
- 返回的是一个空的对象
- object 如果有变量以后打算存储为对象 暂时没想好放啥 这时候就给 null
-
number
- 0 开头会被识别为 八进制
-
string
-
``
- 用来拼接字符 ${}
- 中间可以使用 回车
-
-
undefined
- 在某个时候,想知道,数据到底传给我们没有,可以判断一下,data变量(为了存储后端返回的数据)是否等于 undefined
-
-
复杂数据类型
- 引用类型:通过 new 创建对象 Object Array Date 存放在 堆 里面
- 首先在栈里面存放十六进制表示的地址 然后地址指向堆里的数据
-
-
数据类型传参
- (1) 简单数据类型传参是传结果 原本值不变
- (2) 复杂数据类型传参是传地址 原本值改变
⭐️数据类型转换
-
转化为字符型
-
把数字型转换为字符串型 toString()
var str = num.toString(); -
利用 String(变量)
console.log(String(num)); -
利用 + 拼接字符串的方法实现转换效果 隐式转换
console.log(num + '');
-
-
转换为数字型
-
parseInt(变量) 可以把字符型的转换为数字型 得到的是整数 过滤单位
- 不会四舍五入
- 第一个字不为数字类型时返回NaN,否则,除去后面
console.log(parseInt('3.14')); // 3取整 console.log(parseInt('3.94')); // 3取整 console.log(parseInt('120px')); // 120 去单位 console.log(parseInt('rem120px')); //NaN
-
-
parseFloat(变量) 可以把 字符型的转换为数字型 得到的是小数 浮点数
-
parseFloat("123abc") // 123
-
parseInt和parseFloat(parse解析的意思),若是数字开头的字符串,返回的数字为NaN,第一个数字直到遇到非数字字符,之间的纯数字;
-
-
利用Number(变量)
-
当数据不能转化为数字的时候,会返回 NaN
-
NaN 是一个数字类型
- NaN不等于任何值,包括本身
-
-
利用了算数运算 - * / == != > <隐式转换
console.log('12'-0); // 12 console.log('123'-'120');- 除了加号(+)之外,算术运算符:会把数据类型转化为数字类型
-
注意 ❗️:
-
如果两边都是数值(Number)类型 则是+号运算符
-
+号
-
数字相加
- 只有一个字符串 eg:+prompt('type num:')
-
字符相连
- 左右如果有 一个 数据是字符串数据类型的话 那么这个+号会被解析成连接符
-
-
prompt用户输入的值是 字符串
-
取余
-
开发用法:
- 判断某个数字是否能被整除
- 判断 奇偶:% 2 奇 = 1 偶 = 0
-
💬字符串操作方法
-
concat('字符串 1','字符串 2'...)
-
substr('截取起始索引位置','截取几个字符');
-
替换字符 replace('被替换的字符','替换为的字符') 只会替换一个字符
-
替换多个字符
var str2 = 'anjaohquoao'; while (str2.indexOf('o') !== -1) { // str2.replace('o', '*'); str2 = str2.replace('o', '*'); }
-
-
字符转换为数组 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 引擎运行:
-
预解析
-
把所有的 var function 提升到当前作用域的最前面
-
变量提升
- 把所有变量的声明 提升到当前作用域最前面 不提升赋值
-
-
代码执行
- 按代码书写顺序从上往下执行
// 案例 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 对象:所有具体的事物 属性(特征)与方法(行为)的集合
-
创建对象的方法
-
利用对象字面量创建对象
- var obj = {};
-
var obj = { userName: 'wendy', age: 18, sex: 'man', sayHi: function () { console.log('hi~'); } //方法后面跟的是匿名函数 }
-
利用 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();
-
-
-
调用属性的两种方法
-
对象名.属性名
console.log(obj.age); -
对象名 ['属性名']
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');
-
-
❗️ 注意点
-
构造函数名字首字母要大写
-
构造函数不需要 return 就可以返回结果
-
属性或方法前面一定要用 this
-
调用构造函数一定要用 new
-
new 关键字的执行过程
- new 构造函数可以在内存中创建了一个空的对象
- this 就会指向刚刚创建的空对象
- 指向构造函数里面的代码 给空对象添加属性和方法
- 返回这个对象
-
-
-
遍历对象
- forin 语法
// for (变量 in 对象){} for (let k in obj) { console.log(k); // k/key 变量 输出的是 属性名 console.log(obj[k]); // obj[k] 得到的是 属性值 // 不能用 obj.k }- 先打印出数字类型的属性(排序,小到大),后字符串(俺书写顺序)
✅内置对象
⭐️Math对象
-
查看 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() 幂运算
-
-
利用对象 封装自己 的数学对象 里面有 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])); -
绝对值方法
console.log(Math.abs(-1)); console.log(Math.abs('1')); // 隐式转换 会把字符型转换为数字型 console.log(Math.abs('pink')); // NaN -
三个取整方法
-
(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
-
-
随机数
-
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));
-
-
随机点名
-
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 来调用创建我们的日期对象
-
使用 Date 如果没有参数 返回当前系统的当前时间
-
参数常用方法 数字型 2019, 10, 01 或者是 字符串型 '2019-10-01 8:8:8' h / m / s
-
特殊
var date1 = new Date(2019, 10, 01); console.log(date1); // 返回的是 11 月
-
-
日期格式化
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]); -
格式化日期 时分秒
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; } -
获得 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());
-
-
倒计时案例
-
核心算法:输入时间 - 现在时间 但是时分秒不能直接相减
-
用时间戳来做。输入总秒数 - 现在时间总秒数 = 剩余总秒数
-
剩余时间转化为 天、时、分、秒
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指向问题
-
全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
-
方法调用中谁调用this指向谁
-
构造函数中this指向构造函数的实例
-
bind、call、apply 修改 this 的指向
-
call 和 apply 会在调用原函数的同时也修改 this 的指向
-
call 和 apply 的区别
- 传递参数不同
-
obj.say.call(newObj,1,2) obj.say.apply(newObj,[1,2])
-
-
bind 会帮你修改 this 指向 但是不会直接调用 原函数 而是会返回一个 修改了 this 指向的新函数
-