跟着pink老师课程写的笔记
JS基础
1.运算符
1.1 自增运算符
var e = 10;
var f = e++ + ++e;
// 1. e++ = 10 e = 11
// 2. e = 12 ++e = 12
console.log(f); // 22
1.2 逻辑运算符
1.2.1 逻辑与
有假必假,两边都是true才返回true
对于数值和表达式:
语法: 表达式1 && 表达式2
如果第一个表达式的值为真,则返回表达式2
如果第一个表达式的值为假,则返回表达式1
console.log( 123 && 456 ); // 456
console.log( 0 && 456 ); // 0
console.log( 123 && 456&& 789 ); // 789
1.2.2 逻辑或
有真必真,两边都是false才返回false
对于数值和表达式:
l语法: 表达式1 || 表达式2
l 如果第一个表达式的值为真,则返回表达式1
l 如果第一个表达式的值为假,则返回表达式2
console.log( 123 || 456 ); // 123
console.log( 0 || 456 ); // 456
console.log( 123 || 456 || 789 ); // 123
1.3 运算符优先级
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
1.4 不同类型数据相加减
1.4.1 同类型数据
①布尔类型相加减
true转化为数值1,false转化为数值0,进行数值运算
②字符型相加减
相加首尾连接
相减是根据Number()方法将字符型转化为数值型,再进行减法。如果转化后值为NaN,则最终结果为NaN
1.4.2 不同类型数据
与字符串相加都会变成字符串
数值型和数值字符串相加减,数值字符串会转化为数值,从而结果是数值
数值型和非数值字符串相减,根据Number()方法将字符型转化为数值型,结果是NaN(一般的非数值)
布尔类型和数值相加减,true转化为数值1,false转化为数值0,进行数值运算,结果是数值
undefined和数值相加减结果是NaN
1.5 浮点数的精度问题
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001
所以:不要直接判断两个浮点数是否相等 !
2.函数
1.1 return注意事项
函数都是有返回值的
- 如果有return则返回return后面的值
- 如果没有return则返回undefined
break:结束当前的循环体(如?for、while)
continue:跳出本次循环,继续执行下次循环(如?for、while)
return:不仅可以退出循环,还能够返回?return?语句中的值,同时还可以结束当前的函数体内的代码
1.2 arguments
当我们不确定有多少个参数传递的时候,可以用arguments来获取(原来形参的位置留空)。
在JavaScript中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
伪数组:
- 具有
length
属性 - 按索引方式储存数据
- 不具有数组的push,pop等方法
function maxValue() {
var max = arguments[0];
for (var i = 0; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i];
}
}
return max;
}
console.log(maxValue(2, 4, 5, 9));
console.log(maxValue(12, 4, 9));
1.3 函数声明方式
1.3.1 自定义函数方式(命名函数)
// 声明定义方式
function fn() {
...}
// 调用
fn()
因为有名字,所以也被称为命名函数
调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
1.3.2 函数表达式方式(匿名函数)
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){
...};
// 调用的方式,函数调用必须写到函数体下面
fn();
其中fn是变量名不是函数名
因为函数没有名字,所以也被称为匿名函数
这个fn里面存储的是一个函数
函数表达式方式原理跟声明变量方式是一致的
函数调用的代码必须写到函数体后面
3.作用域
3.1 全局作用域
作用于所有代码执行的环境(整个script标签内部)或者一个独立的js文件。
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
3.2 局部作用域(函数作用域)
作用于函数内的代码环境,就是局部作用域。?因为跟函数有关系,所以也称为函数作用域。
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部
var
声明的变量是局部变量 - 函数的形参实际上就是局部变量
3.3 块级作用域
块作用域由{}
包括。
Js中没有块级作用域(在ES6之前)
3.4 作用域链
l 只要是代码,就至少有一个作用域
l 写在函数内部的局部作用域
l 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
l 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
//输出123,就近原则(一层一层往外查找)
作用域链:采取就近原则的方式来查找变量最终的值。
4.预解析(变量提升)
console.log(num); // 1.报错,num is not defined
console.log(num);
var num = 2; //2.输出 undefined
fn();
function fn() {
console.log('打印');
} //3.输出 打印
fn();
var fn2 = function() {
console.log('想不到吧');
} //4.报错 fn2 is not a function
JS代码是由浏览器中的JS解析器来执行的。
JS解析器在运行JS代码的时候分为两步:预解析
和代码执行
。
- 预解析:在当前作用域下,JS代码执行之前,浏览器会默认把带有var和function声明的变量在内存中进行提前声明(不会进行赋值)或者定义。
- 代码执行:从上到下执行JS语句。
fn();
var fn2 = function() {
console.log('想不到吧');
}
//相当于
var fn2;
fn();
fn2 = function(){
......}
预解析有 变量预解析 和 函数预解析
// 案例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);
//结果:9 9 9 9 9 报错
5.对象
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的。
l 属性:事物的特征,在对象中用属性来表示(常用名词)
l 方法:事物的行为,在对象中用方法来表示(常用动词)
例如保存一个人的完整信息,可以用数组
var arr = [‘张三疯’, ‘男', 128,154];
用 对象 :
person.name = ‘张三疯';
person.sex = ‘男';
person.age = 128;
person.height = 154;
5.1 创建对象的三种方式
5.1.1 利用字面量创建对象
对象字面量:就是花括号{}里面包含了表达这个具体事物(对象)的属性和方法。
{}里面采取键值对的形式表示
l 键:相当于属性名
l 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
5.1.2 利用new Object创建对象
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
alert('大家好啊~');
}
5.1.3 利用构造函数创建对象
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在js中,使用构造函数要时要注意以下两点:
- 构造函数用于创建某一类对象,其首字母要大写
- 构造函数要和new一起使用才有意义
function Star(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
var ldh = new Star('刘德华', 18, '男');
console.log(ldh);
5.1.4 对象的调用
- 对象属性调用: 对象.属性名
- 属性的另一种调用方式: 对象[‘属性名’],注意方括号里面的属性必须加引号,我们后面会用
- 对象方法调用:对象.方法名(),注意这个方法名字后面一定加括号
5.1.5 变量、属性、函数、方法的区别
变量:单独声明赋值,单独存在
属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
函数:单独存在的,通过“函数名()”的方式就可以调用
方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。
5.1.6 遍历对象
for…in语句用于对数组或者对象的属性进行循环操作。
for (变量 in 对象名字) {
//在此执行代码
}
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为k或者key。
for (var k in obj) {
console.log(k); // 这里的 k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
6.内置对象
6.1 Math对象
Math.PI // 圆周率
Math.floor() // 向下取整,往小取值
Math.floor(1.1) //1
Math.floor(-1.1)//-2
Math.ceil() // 向上取整,往大取值
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3(往大取)
Math.abs() // 绝对值
Math.max()/Math.min() // 求最大和最小值
random()//随机返回一个小数,其取值范围是[0,1),左闭右开0<=x<1
随机数方法
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
//随机数乘以两数之差,随机取得两数之差之间的数,加上最小可取的数
这个例子返回了一个在指定值之间的随机整数。这个值不小于 min
(如果 min
不是整数,则不小于 min
的向上取整数),且小于(不等于)max
。
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
//不含最大值,含最小值
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
//含最大值,含最小值
}
6.2 日期对象
日期对象是构造函数,所以我们需要实例化后才能使用(要new)
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
var h = date.getHours();
h = h < 10 ? '0' + h : h;
var m = date.getMinutes();
m = m < 10 ? '0' + m : m;
var s = date.getSeconds();
s = s < 10 ? '0' + s : s;
console.log('今天是' + year + '年' + month + '月' + dates + '日' + days[day] + ' ' + h + ':' + m + ':' + s);
6.3 数组对象
6.3.1 检测是否为数组
instanceof运算符,可以判断一个对象是否属于某种类型
Array.isArray()用于判断一个对象是否为数组,isArray()是HTML5中提供的方法
var arr = [1, 23];
var obj = {
};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
6.3.2 添加删除数组元素的方法
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
newArr.push(arr[i]);
}
}
console.log(newArr);
6.3.3 数组排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0FliWGdO-1618047172807)(https://i.loli.net/2021/03/23/B2VurRYyx3D7wtn.png)]
var arr = [1, 64, 9, 6];
arr.sort(function(a, b) {
return b - a; // 降序
// return a - b; // 升序
});
console.log(arr)
6.3.4 数组索引方法
lastIndexOf()从后面开始查找
6.3.5 数组转换为字符串
arr.join(';')
arr.toString()
6.3.6 连接、截取、删除
6.4 字符串对象
6.4.1 基本包装类型
为了方便操作基本数据类型,JavaScript?还提供了三个特殊的引用类型:String、Number和Boolean。
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。
//?下面代码有什么问题?
var str = 'andy';
console.log(str.length);
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js会把基本数据类型包装为复杂数据类型,其执行过程如下:
//1.生成临时变量,把简单类型包装为复杂数据类型
var temp = new String('andy');
//2.赋值给我们声明的字符变量
str = temp;
//3.销毁临时变量
temp = null;
6.4.2 字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
var str = 'abc';
str = 'hello';
// 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for (var i = 0; i < 100000; i++) {
str += i;
}
console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
6.4.3 根据字符返回位置
var str = '改革春风吹满地,中国人民真争气!'
console.log(str.indexOf('中'));
console.log(str.indexOf('中', 5));
//输出结果是一样的,因为他只是不查找了满字之前(不包括满字)的字符
6.4.4 根据位置返回字符(重点)
6.4.5 字符串操作方法(重点)
6.4.6 替换字符串-replace()方法
replace()方法用于在字符串中用一些字符替换另一些字符。
replace(被替换的字符串,要替换为的字符串);
只替换第一个字符
6.4.7 切分字符串-split()方法
var str = 'a,b,c,d';
console.log(str.split(',')); // 返回的是一个数组 [a, b, c, d]
6.4.8 大小写转换
toUpperCase() //转换大写
toLowerCase()//转换小写
7.简单类型与复杂类型
7.1 定义
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型string,number,boolean,undefined,null
- 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等
7.2 堆和栈
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3lTujijq-1618047249923)(https://i.loli.net/2021/03/25/RlZ9jrpVnGUhTcJ.png)]
注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
7.3 简单类型的内存分配
值类型(简单数据类型):string,number,boolean,undefined,null
值类型变量的数据直接存放在变量(栈空间)中
7.4 复杂类型的内存分配
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间
7.5 简单类型传参
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) {
a++;
console.log(a);//这里输出11
}
var x = 10;
fn(x);
console