JavaScript基础语法和知识
个人学习笔记
- 学习地址:JavaScript前端课程-dom-bom-js-es6新语法-jQuery-数据可视化echarts黑马pink老师前端入门基础视频教程(500多集)持续_哔哩哔哩_bilibili
- 配套资料:
P1
注意:
- 变量
- var不确认数据类型,只有在赋值时候才确定
- js是动态语言,变量的数据类型是可以变化的
- 进制
- 数字前面加0 表示八进制
- 数字的前面加 0x 表示十六进制
- 字符串型
- 嵌套:外双内单,外单内双
- 转义字符:要写到引号里面,eg. \t缩进(tab),\b空格
- 拼接:用+,字符串和其他类型拼接最终结果是字符串
- 布尔型和数字型相加的时候,true 的值为 1 ,false 的值为 0
- 使用表单、prompt 获取过来的数据默认是字符串类型的
- 类型转换
- 数字转成字符串型:
console.log(num + '');//+空字符串
- 字符型转成数字型:
- parseInt:取整,去掉px单位
console.log(parseInt('3.14')); // 3 取整
- parseFloat:不取整,去掉px单位
console.log(parseFloat('3.14')); // 3.14
- Number( )、隐式转换(-、 *、/)
- parseInt:取整,去掉px单位
- 其他类型转化为布尔值:
(Boolean()
,代表空、否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined,其他trueconsole.log(Boolean(''));
- 数字转成字符串型:
常用:
- console.log(num):控制台输出一个变量num,eg.
console.log(isNaN(12)); // false
,console.log(str.length); //字符串长度
,console.log(typeof num)
- alert():弹出
- eg.1 提示输入并弹出输入内容
var age = prompt('请输入您的年龄'); //这是字符型 var str = '您今年已经' + age + '岁了'; alert(str);
- eg.1 提示输入并弹出输入内容
P2
- 运算符
- 2个浮点数相加有精度问题
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
- 前置自增和后置自增
- 单独使用num++、++num效果相同,都相当于num=num+1
- 注意:后置自增,先返回原值,后自加,前置自增反之
var num = 10; alert(10 + num++); // 20
- 易错练习:
var f = e++ + ++e; // 1. e++ = 10 e = 11 2. e = 12 ++e = 12 f=22
- 比较运算符
- ==会转型(只判断值),会把字符串型转化为数字型
console.log(18 == '18'); // true
- ===要求两侧的值还有数据类型完全一致才可以true
- ==会转型(只判断值),会把字符串型转化为数字型
- 逻辑运算符:与、或、非
- 短路运算:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值
- 表达式1 && 表达式2:1为真,返回2;1为假返回1
console.log('' && 1 + 2 && 456 * 56789); // ''前为假返回前的空字符串
- 表达式1 || 表达式2:1为真返回1;1为假返回2;
- 表达式1 && 表达式2:1为真,返回2;1为假返回1
- 短路运算:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值
- 2个浮点数相加有精度问题
- 流程控制
- 顺序
- 分支(2种):
- if:选一个执行
- switch
- 循环
常用代码段:
-
分支1(if-多选一)
- 1个if
var age = prompt('请输入您的年龄:'); if (age >= 18) {//是则完成,不是则不完成 alert('我想带你去网吧偷耳机'); }
- 双分支语句if-else
var age = prompt('请输入您的年龄:'); if (age >= 18) { alert('我想带你去网吧偷耳机'); } else { alert('滚, 回家做作业去'); }
- 多分支语句(范围判断)
var score = prompt('请您输入分数:'); if (score >= 90) { alert('宝贝,你是我的骄傲'); } else if (score >= 80) { alert('宝贝,你已经很出色了'); } else if (score >= 70) { alert('你要继续加油喽'); } else if (score >= 60) { alert('孩子,你很危险'); } else { alert('熊孩子,我不想和你说话,我只想用鞭子和你说话'); }
- 1个if
-
三元表达式:条件表达式 ? 表达式1 : 表达式2
var result = num > 5 ? '是的' : '不是的'; // 我们知道表达式是有返回值的 console.log(result);//是的
-
switch:switch后的表达式和case后的相比较(确定,分支多用)
注意:这个比较是全等**,且要有break否则输出当前往后的所有值**
switch (2) { case 1: console.log('这是1'); break; case 2: console.log('这是2'); break;//直接跳到2,前后都不执行了 case 3: console.log('这是3'); break; default: console.log('没有匹配结果'); }//是2
P3 3个循环
- 循环1-for循环
- 1个for循环
for (var i = 1; i <= 100; i++) { console.log('你好吗'); } //初始化变量 就是用var 声明的一个普通变量, 通常用于作为计数器使用 //条件表达式 就是用来决定每一次循环是否继续执行 就是终止的条件 //操作表达式 是每次循环最后执行的代码 经常用于我们计数器变量进行更新(递增或者递减)
- for循环+分支
for (var i = 1; i <= 100; i++) { if (i == 1) { console.log('这个人今年1岁了,他出生了'); } else if (i == 100) { console.log('这个人今年100岁了,他死了'); } else { console.log('这个人今年' + i + '岁了'); } }
- for循环嵌套
for (var i = 1; i <= 3; i++) { console.log('这是外层循环第' + i + '次'); for (var j = 1; j <= 3; j++) { console.log('这是里层的循环第' + j + '次'); } }
- 1个for循环
- 断点调试
-
打开f12,点击源代码,双击左侧的文件打开
-
打断点(单击一下行数),然后刷新页面(旋转说明卡在这了)
-
点击下一步,不断重复会做一个又一个循环(i≤100,输出,i++的循环)
-
把鼠标放在变量上可以看到变量的值
-
可以在监视(watch)选择添加,输入i,就可以看到i是多少了
-
取消断点直接再点一下第几行的数字取消
-
- 循环2-while循环:注意不要造成死循环
while (message !== '我爱你') { message = prompt('你爱我吗?'); }
- 循环3-do while:先执行循环体,再判断条件
// 1.do while 循环 语法结构 do { // 循环体 } while (条件表达式) // 2. 执行思路 跟while不同的地方在于 do while 先执行一次循环体 在判断条件 如果条件表达式结果为真,则继续执行循环体,否则退出循环 // 3. 代码验证 var i = 1; do { console.log('how are you?'); i++; } while (i <= 100) // 4. 和while不同点:do while 循环体至少执行一次
- continue关键字
- 用于立即跳出本次循环,继续下一次循环(本次循环体中 continue之后的代码就会少执行1次)
- eg. 求1~100 之间, 除了能被7整除之外的整数和
// 1. 求1~100 之间, 除了能被7整除之外的整数和 var sum = 0; for (var i = 1; i <= 100; i++) { if (i % 7 == 0) { continue; } sum += i; } console.log(sum);
- break:
- 跳出整个循环
- eg. 吃第3个包子不吃了
// break 退出整个循环 for (var i = 1; i <= 5; i++) { if (i == 3) { break; } console.log('我正在吃第' + i + '个包子'); }
- 注意:
- 从prompt取过来的数据是字符串型的要转化成数字
var score = prompt('请您输入第' + i + '个学生成绩'); // 因为从prompt取过来的数据是 字符串型的需要转换为数字型 sum = sum + parseFloat(score);
- 字符串可以相加
str = str + '★'
,str的初始化var str = '';
- JavaScript有3种循环,for循环常用
- 从prompt取过来的数据是字符串型的要转化成数字
P4 数组和函数
- 创建数组(2种)
- new创建
- 字面量创建(常用)
var arr = new Array(); //1.用new 创建了一个空的数组 // 2. 利用数组字面量创建数组 [] var arr = []; // 创建了一个空的数组 var arr1 = [1, 2, 'pink老师', true];
- 遍历数组
- 数组长度:
alert(arrStus.length);
- for循环遍历
for(var i = 0; i < arr.length; i++){ console.log(arrStus[i]); }
- 数组长度:
- 新增数组元素
- 修改length长度来扩容:直接赋值
arr.length = 5;
// 1. 新增数组元素 修改length长度 var arr = ['red', 'green', 'blue']; console.log(arr.length); arr.length = 5; // 把我们数组的长度修改为了 5 里面应该有5个元素 console.log(arr); console.log(arr[3]); // undefined console.log(arr[4]); // undefined
- 修改索引号对应内容,追加、替换元素:
arr1[3] = 'pink';
var arr1 = ['red', 'green', 'blue']; arr1[3] = 'pink'; console.log(arr1); arr1[4] = 'hotpink'; console.log(arr1); arr1[0] = 'yellow'; // 这里是替换原来的数组元素 console.log(arr1); arr1 = '有点意思'; console.log(arr1); // 不要直接给 数组名赋值 否则里面的数组元素都没有了
- 修改length长度来扩容:直接赋值
- 筛选数组
// 方法2 选出大于10的数字 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; // 刚开始 newArr.length 就是 0 for (var i = 0; i < arr.length; i++) { if (arr[i] >= 10) { // 新数组索引号应该从0开始 依次递增 newArr[newArr.length] = arr[i]; } }
- 冒泡排序:5 4 3 2 1变成从小到大
-
第一趟:依次比较,5和4比较,变成4 5;5和3比较,变成3 5,直到5变到最后
-
代码
var arr = [4, 1, 2, 3, 5]; for (var i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数 for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数 // 内部交换2个变量的值 前一个和后面一个数组元素相比较 if (arr[j] < arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr);
-
- 函数的使用
//1.不带参数的 function sayHi() { console.log('hi~~'); } sayHi();
//2.带参数的求和函数 function getSum(num1, num2) {//形参:接收实参, 形参的默认值为 undefined var sum = 0; for (var i = num1; i <= num2; i++) { sum += i; } console.log(sum); } getSum(1, 100);//实参
- 形参实参个数不匹配:这点不同于java
function getSum(num1, num2) { console.log(num1 + num2); }
- 如果实参的个数=形参的个数 则正常输出结果:
getSum(1, 2);//3
- 如果实参的个数>形参的个数,会取到形参的个数:
getSum(1, 2, 3);//1+2=3,第3个实参不参与运算
- 如果实参的个数<形参的个数,少的部分的形参可以看做是不用声明的变量, num2 是一个变量但是没有接受值,即undefined:
getSum(1); // num1(1)+num2(undefined) = NaN
- 如果实参的个数=形参的个数 则正常输出结果:
- 函数返回值:
- 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名(),通过return 实现的
- 只要函数遇到return 就把后面的结果 返回给函数的调用者,函数名() = return后面的结果
- 注意:
- return 会终止函数
- return 只会返回一个值(返回的结果是最后一个值,也可以返回数组)
- 如果函数没有,return 则返回undefined
function getSum(num1, num2) { return num1 + num2; alert('我是不会被执行的哦!') } console.log(getSum(1, 2)); //返回数组 function getResult(num1, num2) { return [num1 + num2, num1 - num2, num1 * num2, num1 / num2]; } var re = getResult(1, 2); // 返回的是一个数组 console.log(re);
- arguments的使用
- 当我们不确定有多少个参数传递的时候,形参会很难写,因为不知道有多少个参数传递进来,可以用 arguments 来获取。
- 在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。每个函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。
- arguments展示形式是一个伪数组,不是真正意义的数组,有以下3个特性
- 具有数组的 length 属性
- 按照索引的方式进行存储的
- 它没有真正数组的一些方法eg. pop(),push() 等
// arguments 的使用 只有函数才有 arguments对象 而且是每个函数都内置好了这个arguments function fn() { console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3] console.log(arguments.length); console.log(arguments[2]); // 我们可以按照数组的方式遍历arguments for (var i = 0; i < arguments.length; i++) { console.log(arguments[i]); } } fn(1, 2, 3);
- 函数练习案例
//1.翻转数组函数 function reverse(arr) { var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } return newArr; } //1,测试 var arr1 = reverse([1, 3, 4, 6, 9]); console.log(arr1); var arr2 = reverse(['red', 'pink', 'blue']); console.log(arr2); //2. 利用函数冒泡排序 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; } //2,测试 var arr1 = sort([1, 4, 2, 9]); console.log(arr1); var arr2 = sort([11, 7, 22, 999]); console.log(arr2);
- 函数声明(2种)
- 命名函数:利用函数关键字自定义函数
function fn() { } fn();
- 函数表达式:因为没有名字又称为匿名函数
var fun = function(aru) { console.log('我是函数表达式'); console.log(aru); } fun('pink老师');
- 命名函数:利用函数关键字自定义函数
P5 作用域和对象
-
作用域
- JavaScript作用域 : 就是代码名字(变量)在某个范围内起作用和效果,目的是为了提高程序的可靠性,更重要的是减少命名冲突
- 分类(es6之前)
- 全局作用域:整个script标签,或者是一个单独的js文件
- 局部作用域 :在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用
- 全局和局部同名字的变量不会影响
-
变量的作用域
- 全局变量:在全局作用域下的变量 在全局下都可以使用注意例子
var num = 10; // num就是一个全局变量 console.log(num);//第1个10 function fn() { console.log(num);//第2个10, 可以访问外面的 } fn(); //注意:这里会输出2个10
- 局部变量:在局部作用域下的变量,后者在函数内部的变量就是局部变量
- 注意
- 如果在函数内部,没有声明直接赋值的变量也属于全局变量。注意例子:num2没有在函数内部声明直接赋值也是全局变量,但是可以在函数外输出值
function fun(aru) { var num1 = 10; // num1就是局部变量 只能在函数内部使用 num2 = 20; } fun(); // console.log(num1);//不能输出因为是局部变量 console.log(num2);//20
- 函数的形参也可以看做是局部变量,因为形参不可以输出值是no defind
- 如果在函数内部,没有声明直接赋值的变量也属于全局变量。注意例子:num2没有在函数内部声明直接赋值也是全局变量,但是可以在函数外输出值
- 执行效率
- 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
- 当我们程序执行完毕就会销毁, 比较节约内存资源
- 全局变量:在全局作用域下的变量 在全局下都可以使用注意例子
-
块级作用域
- 在 es6 的时候才新增的块级作用域
- 块级作用域是有 {}包含的,eg. if {},for {}
- java里面有块级作用域,在大括号里面声明的变量外面是不能调用的
// if(xx) { // int num = 10; // } // 外面的是不能调用num的
- 目前学到JavaScript(js)是没有块级作用域的,因此可以调用
if (3 < 5) { var num = 10; } console.log(num);//这里是可以调用{}里面的num
-
作用域链
- 只要是代码都一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中;
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在 [内部函数可以访问外部函数变量] 的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
- 这里链式查找是,一层一层往上一级找,看哪些数据可以调用
- 注意例子:num有10,20,就近原则。fun()里面的num在一层一层往上找,没有找到就继续找,找到了就输出
// 作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链 就近原则 var num = 10; function fn() { // 外部函数 var num = 20; function fun() { // 内部函数 console.log(num); } fun(); } fn(); // 输出是20
- 作用域链案例
function f1() { var num = 123; function f2() { // var num = 0; console.log(num); // 站在目标出发,一层一层的往外查找 } f2(); } var num = 456; f1();//有0那行输出0,0最近;如果没有0那行输出123
-
预解析
- JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。
- JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
- 预解析: js引擎会把js 里面所有的 var还有 function 提升到当前作用域的最前面
- 代码执行:按照代码书写的顺序从上往下执行
- 预解析分为:变量预解析(变量提升)和 函数预解析(函数提升)
- 变量提升:把所有的变量声明提升到当前的作用域最前面,不提升赋值操作
console.log(num); // undefined var num = 10; // 相当于执行了以下代码 // var num; // console.log(num); // num = 10;
- 函数提升:把所有的函数声明提升到当前作用域的最前面,不调用函数
fun(); // 报错 var fun = function() { console.log(22); } // 函数表达式 调用必须写在函数表达式的下面 // 相当于执行了以下代码 // var fun; // fun();// 相当于调用了一个没有的函数,肯定报错 // fun = function() { // console.log(22); // }
// 没问题 相当于把fn(){}提到了前面 fn(); function fn() { console.log(11); }
- 变量提升:把所有的变量声明提升到当前的作用域最前面,不提升赋值操作
- 预解析案例:先按照预解析排号,再按照作用域链查找值
// 案例1 输出undefined和20 var num = 10; function fn() { console.log(num); var num = 20; console.log(num); } fn(); // 相当于以下代码 // var num; // function fn() { // var num; // console.log(num); //往函数里的第一行var num;找,输出undefined // num = 20; // console.log(num); //就近找到上一行的20,输出20 // } // num = 10; // fn();
// 案例2 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;// 这里要特别注意b和c没有var是全局变量 // a = b = c = 9; // // 相当于 var a = 9; b = 9; c = 9;b和c直接赋值, 函数内没有var声明当全局变量看 // // 集体声明 var a = 9, b = 9, c = 9; 这样才相当于var a;var b;var c; // console.log(a);//在这层里找,输出9 // console.log(b);//在这层里找,输出9 // console.log(c);//在这层里找,输出9 // } // f1(); // console.log(c); //b和c全局变量在这里任何地方都可以使用所以输出9 // console.log(b); //b和c全局变量在这里任何地方都可以使用所以输出9 // console.log(a); //a是局部变量,不能访问,报错
-
对象
- 在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
- 对象是由属性和方法组成的。
- 注意:
- 泛指不算对象,eg. 狗不是对象,这个狗是对象
- 对象:属性、方法;单独的:变量、函数
-
创建对象的三种方式
- 利用对象字面量方式
var obj = {};
- 创建对象
var obj = { uname: '张三疯',//属性 age: 18, sex: '男', sayHi: function() { console.log('hi~'); } } // (1) 里面的属性或者方法我们采取键值对的形式 键(属性名):值(属性值) // (2) 多个属性或者方法中间用逗号隔开的 // (3) 方法冒号后面跟的是一个匿名函数
- 对象调用
// (1). 调用对象的属性 我们采取 对象名.属性名 . 我们理解为 的 console.log(obj.uname);//张三疯 // (2). 调用属性还有一种方法 对象名['属性名'] console.log(obj['age']);//男 // (3) 调用对象的方法 sayHi 对象名.方法名() 千万别忘记添加小括号 obj.sayHi();//输出hi~
- 创建对象
- 利用new object方式
- 创建对象:利用
=
赋值的方法添加对象的属性和方法,每个属性和方法之间用;
结束// 利用 new Object 创建对象 var obj = new Object(); // 创建了一个空的对象 obj.uname = '张三疯';//加属性 obj.age = 18; obj.sex = '男'; obj.sayHi = function() {//加方法 console.log('hi~'); }
- 对象调用
console.log(obj.uname); console.log(obj['sex']); obj.sayHi();
- 创建对象:利用
- 利用构造函数方式
- 构造函数:泛指的某一大类,它类似于 java语言里面的类(class)
- 前面两种创建对象的方式一次只能创建一个对象
- 因为我们一次创建一个对象,里面很多的属性和方法是大量相同的,我们只能复制
- 因此我们可以利用函数的方法,重复这些相同的代码
- 又因为这个函数不一样,里面封装的不是普通代码,而是对象,我们就把这个函数称为:构造函数
- 构造函数:就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
- 注意:构造函数
// 构造函数的语法格式 // function 构造函数名() { // this.属性 = 值; // this.方法 = function() {} // } // new 构造函数名(); function Star(uname, age, sex) {// 构造函数的首字母要大写 this.name = uname;//需要被覆盖的对象的相同的属性要用this写好 this.age = age; this.sex = sex; this.sing = function(sang) { console.log(sang); } }
- 对象实例:具体的事物
- 要用new来创建对象
// new关键字执行过程: // 1. new 构造函数可以在内存中创建了一个空的对象 // 2. this 就会指向刚才创建的空对象 // 3. 执行构造函数里面的代码 给这个空对象添加属性和方法 // 4. 返回这个对象,所以构造函数不需要写return
- 以下代码:刘德华 == {name: “刘德华”, age: 18, sex: “男”, sing: ƒ}
var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象 console.log(typeof ldh);//用来检测数据类型,输出结果:object console.log(ldh.name);//输出结果:刘德华 console.log(ldh['sex']);//输出结果:男 ldh.sing('冰雨'); //给对象的函数传了实参(对应this.sing的sang) var zxy = new Star('张学友', 19, '男');//创建另一个对象
- 要用new来创建对象
- 构造函数:泛指的某一大类,它类似于 java语言里面的类(class)
- 利用对象字面量方式
-
遍历对象for in
- for循环遍历需要有序号,但是这是无序的,所以使用for in(可以对数组、对象,但是一般用在对象的循环)
- 注意
k
是属性名,obj[k]
是属性值
var obj = { name: 'pink老师', age: 18, sex: '男', fn: function() {}//也可以遍历方法 } for (var k in obj) {//for (变量 in 对象) console.log(k); // k 变量 输出得到的是 属性名 console.log(obj[k]); // obj[k] 得到是 属性值 } // 我们使用 for in 里面的变量 我们喜欢写 k 或者 key
P6
-
内置对象
- 概念:指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法),eg. Math、 Date 、Array、String等
-
查文档
- 可以使用:MDN/W3C来查询
- MDN常用:Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及HTML5 应用的 API,地址:https://developer.mozilla.org/zh-CN/
- 学习对象中的方法
-
查阅该方法的功能:搜索max( )或者中文最大值,查看功能
-
查看里面参数的意义和类型
-
查看返回值的意义和类型
-
通过 demo 进行测试
-
-
Math内置对象
-
打开MDN搜索Math
-
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员
-
语法:
Math.max(value0, value1, /* … ,*/ valueN)
,注意:有一个不是数字返回NaN -
random( )方法
- Math对象随机数方法 random() 返回一个随机的小数 0 =< x < 1
- 这个方法里面不跟参数
console.log(Math.random());
- 得到两个数之间的随机整数 并且 包含这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 = ['张三', '张三丰', '张三疯子', '李四', '李思思', 'pink老师']; // console.log(arr[0]); console.log(arr[getRandom(0, arr.length - 1)]);
-
其他方法
// 1.绝对值方法 console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型 console.log(Math.abs('pink')); // NaN // 2.三个取整方法 // (1) Math.floor() 地板 向下取整 往最小了取值 console.log(Math.floor(1.1)); // 1 // (2) Math.ceil() ceil 天花板 向上取整 往最大了取值 console.log(Math.ceil(1.1)); // 2 // (3) Math.round() 四舍五入 其他数字都是四舍五入,但是 .5 特殊 它往大了取 console.log(Math.round(1.1)); // 1 console.log(Math.round(1.5)); // 2 console.log(Math.round(-1.1)); // -1 console.log(Math.round(-1.5)); // 这个结果是 -1,-1和-2大的取-1
-
-
封装自己的数学对象
- 利用字面量方式创建
vara myMath = { }
- 包含键值对形式属性
PI: 3.141592653,
- 包含方法
PI: 3.141592653, max: function() { var max = arguments[0]; for (var i = 1; i < arguments.length; i++) { if (arguments[i] > max) { max = arguments[i]; } } return max; }
- 利用字面量方式创建
-
日期内置对象Date
-
是一个构造函数(要new),必须使用new 来调用创建我们的日期对象
var arr = new Array(); // 创建一个数组对象 var obj = new Object(); // 创建了一个对象实例 // 1. 使用Date 如果没有参数 返回当前系统的当前时间 var date = new Date(); console.log(date);
-
参数常用的写法
- 数字型
- 字符串型
var date1 = new Date(2019, 10, 1); console.log(date1); // 返回的是 11月 不是 10月 var date2 = new Date('2019-10-1 8:8:8'); console.log(date2);//对的,返回10.1
-
格式化
var date = new Date(); console.log(date.getFullYear()); // 返回当前日期的年 2019 console.log(date.getMonth() + 1); // 月份 返回的月份小1 记得月份+1 呦 console.log(date.getDate()); // 返回的是 几号 console.log(date.getDay()); //周一返回的是 1 周六返回的是 6 但是 周日返回的是 0 // 我们写一个 2019年 5月 1日 星期三 var year = date.getFullYear(); var month = date.getMonth() + 1;//因为会小一个月 var dates = date.getDate(); var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; var day = date.getDay(); console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
//格式化时分秒 // 要求封装一个函数返回当前的时分秒 格式 08:08:08 function getTimer() { var time = new Date();//注意Date要new 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; } console.log(getTimer());
-
获取总毫秒数(4种方法),即时间戳
- Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数
- valueOf():
console.log(date.valueOf());
// 就是 我们现在时间 距离1970.1.1 总的毫秒数 - getTime():
console.log(date.getTime());
- 常用写法:
var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数 console.log(date1);
- H5 新增的获得总的毫秒数:
console.log(Date.now());
-
倒计时
- 思路:输入的时间减去现在的时间就是剩余的时间
- 注意:但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。所以用不重复的时间戳做,用户输入时间总的毫秒数减去现在时间的总的毫秒数。把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
- 换算公式
d = parseInt(总秒数/ 60/60 /24); // 计算天数 h = parseInt(总秒数/ 60/60 %24) // 计算小时 m = parseInt(总秒数 /60 %60 ); // 计算分数 s = parseInt(总秒数%60); // 计算当前秒数
- 代码实现(记住)
function countDown(time) { var nowTime = +new Date(); // 括号为空,返回的是当前时间总的毫秒数 var inputTime = +new Date(time); // 括号不为空,返回的是用户输入时间总的毫秒数 var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数,毫秒数换成秒数,1秒=1000毫秒 var d = parseInt(times / 60 / 60 / 24); // 天,parseInt将字符串转换为整数 d = d < 10 ? '0' + d : d; var h = parseInt(times / 60 / 60 % 24); //时 h = h < 10 ? '0' + h : h; var m = parseInt(times / 60 % 60); // 分 m = m < 10 ? '0' + m : m; var s = parseInt(times % 60); // 当前的秒 s = s < 10 ? '0' + s : s; return d + '天' + h + '时' + m + '分' + s + '秒'; } console.log(countDown('2019-5-1 18:00:00')); var date = new Date(); console.log(date);
-
-
数组内置对象
-
创建数组的两种方式:字面量,new Array()
// 1. 利用数组字面量 var arr = [1, 2, 3]; console.log(arr[0]); // 2. 利用new Array() // var arr1 = new Array(); // 创建了一个空的数组 // var arr1 = new Array(2); // 这个2 表示 数组的长度为 2 里面有2个空的数组元素 var arr1 = new Array(2, 3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3 console.log(arr1);
-
检测是否为数组的两种方法
- instanceof:
var arr = []; var obj = {}; console.log(arr instanceof Array);//返回true console.log(obj instanceof Array);//返回false
- Array.isArray(参数):
// (2) Array.isArray(参数); H5新增的方法 ie9以上版本支持 console.log(Array.isArray(arr)); console.log(Array.isArray(obj));
- instanceof:
-
添加删除数组元素的方法
// 1. push() 在我们数组的末尾 添加一个或者多个数组元素 push 推 var arr = [1, 2, 3]; // arr.push(4, 'pink');可以添加多个元素 console.log(arr.push(4, 'pink'));//返回值5,数组的长度 console.log(arr);//返回数组 // (1) push 是可以给数组追加新的元素 // (2) push() 参数直接写 数组元素就可以了 // (3) push完毕之后,返回的结果是 新数组的长度 // (4) 原数组也会发生变化 // 2. unshift 在我们数组的开头 添加一个或者多个数组元素 其他和push一样 console.log(arr.unshift('red', 'purple')); console.log(arr); // (1) unshift是可以给数组前面追加新的元素 // (2) unshift() 参数直接写 数组元素就可以了 // (3) unshift完毕之后,返回的结果是 新数组的长度 // (4) 原数组也会发生变化 // 3. pop() 它可以删除数组的 最后一个元素 console.log(arr.pop());//返回删除的那个元素 console.log(arr);//无参数 // (1) pop是可以删除数组的最后一个元素 记住一次 只能删除一个元素 // (2) pop() 没有参数 // (3) pop完毕之后,返回的结果是 删除的那个元素 // (4) 原数组也会发生变化 // 4. shift() 它可以删除数组的第一个元素 其他和pop一样 console.log(arr.shift()); console.log(arr); // (1) shift是可以删除数组的第一个元素 记住一次只能删除一个元素 // (2) shift() 没有参数 // (3) shift完毕之后,返回的结果是 删除的那个元素 // (4) 原数组也会发生变化
-
数组翻转:
arr.reverse();
-
数组冒泡排序:
arr1.sort( );
//但是有时候不行,所以一般的写法如下( 记住 ): arr1.sort(function(a, b) { // return a - b; 升序的顺序排列 return b - a; // 降序的顺序排列 });
-
返回数组元素索引号:
- 从前面查找:
console.log(arr.indexOf('blue'));
,其中blue
是元素,但是注意:多个blue只返回第一个索引号,找不到返回-1 - 从后面查找:
console.log(arr.lastIndexOf('blue'));
//案例:数组去重 //思路:arr.indexOf(),找不到则返回-1 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; }
- 从前面查找:
-
数组转换为字符串的两种方式
- toString() :以逗号为分割符
- join(分隔符):想用什么分隔符都行
// 1. toString() 将我们的数组转换为字符串 var arr = [1, 2, 3]; console.log(arr.toString()); // 1,2,3 // 2. join(分隔符) var arr1 = ['green', 'blue', 'pink']; console.log(arr1.join()); // green,blue,pink console.log(arr1.join('&')); // green&blue&pink
-
其他方法
-
-
字符串对象
-
基本包装类型:把简单数据类型包装成为了复杂数据类型
var str = 'andy'; console.log(str.length); //按理说str是简单数据类型,不应该有属性,所以是基本包装类型过程 //以上两行相当于以下操作: // (1) 把简单数据类型包装为复杂数据类型 var temp = new String('andy'); // (2) 把临时变量的值 给 str str = temp; // (3) 销毁这个临时变量 temp = null;
-
字符串的不可变性:
- 在多次赋值同一个变量名的过程中,原先的内容不变,但其实是变量指向的地址变了,指向了内存中新开辟了的一个内存空间。所以不要经常拼接字符串(原来的还存在),不要一直重复赋值
- 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。
-
根据字符返回位置的两种方法
- indexOf(): 返回指定内容在元字符串中的位置,如果找不到就返回 -1,开始的位置是index 索引号
// 字符串对象 根据字符返回位置 str.indexOf('要查找的字符', [起始的位置]),[]指的是可以有可以没有 var str = '改革春风吹满地,春天来了'; console.log(str.indexOf('春')); console.log(str.indexOf('春', 3)); // 第二个参数:从索引号3的位置开始往后查找
- lastIndexOf(): 同理,但是从后往前找,只找第一个匹配的
- 案例:查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
var str = "oabcoefoxyozzopp"; var index = str.indexOf('o'); var num = 0; // console.log(index); while (index !== -1) {//第二行查找返回的结果不是-1(有找到) console.log(index);//当前的index num++; index = str.indexOf('o', index + 1);//从index的下一个开始查找0 } console.log('o出现的次数是: ' + num);
- indexOf(): 返回指定内容在元字符串中的位置,如果找不到就返回 -1,开始的位置是index 索引号
-
根据位置返回字符(重点)
// 根据位置返回字符 // 1. charAt(index) 根据位置返回字符 var str = 'andy'; console.log(str.charAt(3));//y // 遍历输出所有的字符 for (var i = 0; i < str.length; i++) { console.log(str.charAt(i)); } // 2. charCodeAt(index) 返回相应索引号的字符ASCII值,目的:判断用户按下了那个键 console.log(str.charCodeAt(0)); // 97 // 3. str[index] H5 新增的 console.log(str[0]); // a
-
判断是否对象有某个属性:
对象['属性名']
// 有一个对象o 来判断是否有该属性 对象['属性名'] var o = { age: 18//属性 } if (o['age']) {//如果对象o有这个属性 console.log('里面有该属性'); } else { console.log('没有该属性'); }
// 遍历对象,得到最大值和该字符 //1.o里面有所有字符属性并存着个数,结果如下图 var str = 'abcoefoxyozzopp'; var o = {};//定义一个对象o for (var i = 0; i < str.length; i++) { var chars = str.charAt(i); // chars 是 字符串的每一个字符eg.'a' if (o[chars]) { // o[chars] 得到的是属性值,如果遍历过程中有这个属性则++,eg.o['a'] o[chars]++; } else { o[chars] = 1; } } console.log(o);
// 2. 遍历对象,求最大值 var max = 0; var ch = ''; for (var k in o) { // k 得到是 属性名 // o[k] 得到的是属性值 if (o[k] > max) { max = o[k]; ch = k; } } console.log(max);//4 console.log('最多的字符是' + ch);//o
-
字符串操作方法(重点)
-
其他方法:
- replace()方法:只替换第一个字符
replace(被替换的字符串, 要替换为的字符串);
// 有一个字符串 'abcoefoxyozzopp' 要求把里面所有的 o 替换为 *(敏感词) var str1 = 'abcoefoxyozzopp'; while (str1.indexOf('o') !== -1) {//找得到 str1 = str1.replace('o', '*'); } console.log(str1);
- 字符转换为数组 split(‘分隔符’) ,前面我们学过 join 把数组转换为字符串
// 2. 字符转换为数组 split('分隔符') 前面我们学过 join 把数组转换为字符串 var str2 = 'red, pink, blue'; console.log(str2.split(','));//输出数组:["red","pink","blue"] var str3 = 'red&pink&blue'; console.log(str3.split('&'));//输出数组:["red","pink","blue"]
- replace()方法:只替换第一个字符
-
-
简单类型与复杂类型
- 简单类型:
- 简单类型又叫做基本数据类型或者值类型,在存储时变量中存储的是值本身,因此叫做值类型string ,number,boolean,undefined,null(注意null返回是一个空对象object)
- 简单数据类型 是存放在栈里面 里面直接开辟一个空间存放的是值
- 如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给 null
- 复杂类型:
- 复杂类型又叫做引用类型,引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型通过 new 关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等
- 首先在栈里面存放地址 十六进制表示 然后这个地址指向堆里面的数据
- 简单类型:
-
堆和栈
- 操作系统把内存分为堆和栈两个部分
- 栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
- 堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面
-
传参
-
简单数据类型:因为传递值,外面结果没有变化
-
复杂数据类型:因为传递地址,外面结果有变化
-