1.5-undefined与null区别
- undefined : 未定义。 当变量只声明,但是没有赋值。此时默认值是undefined
- null : 有定义。 定义的值是空值。
- 相同点 : (1)值相等 (2)转布尔类型都是false
- 不同点 : (1)数据类型不同 (2)转number类型值不同
逻辑非(!)
逻辑非操作符会遵循如下规则:
- 如果操作数是对象,则返回false
- 如果操作数是空字符串,则返回true
- 如果操作数是非空字符串,则返回false
- 如果操作数是数值0,则返回true
- 如果操作数是非0数值,则返回false
- 如果操作数是null,则返回true
- 如果操作数是NaN,则返回true
- 如果操作数是undefined,则返回true
console.log(!false); // true
console.log(!"blue"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!12345); // false
复制代码
拓展 逻辑非操作符可以用于把任意值转换为布尔值。同时使用两个叹号(!!),相当于调用了转型函数Boolean()。
console.log(!!"blue"); // true
console.log(!!0); // false
console.log(!!NaN); // false
console.log(!!""); // false
console.log(!!12345); // true
复制代码
逻辑与(&&)
- 如果&&两边的操作数都是布尔值,则只有两个值都为true的时候才返回true,其余情况都返回false
- 如果有操作数不是布尔值,则逻辑与并不一定返回布尔值,而是遵循如下规则:
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象
- 如果两个操作数都是对象,则返回第二个操作数
- 如果有一个操作数是
null,则返回null - 如果有一个操作数是
NaN,则返回NaN - 如果有一个操作数是
undefined,则返回undefined
逻辑与操作符是一种短路操作符,对逻辑与操作符来说,如果第一个操作数是false,那么无论第二个操作数是什么值,结果也不可能等于true。
逻辑或(||)
- 如果||两边的操作数都是布尔值,则只有两个值都为false的时候才返回false,其余情况都返回true
- 如果有操作数不是布尔值,则逻辑与并不一定返回布尔值,而是遵循如下规则:
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数求值为false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数
- 如果有一个操作数是
null,则返回null - 如果有一个操作数是
NaN,则返回NaN - 如果有一个操作数是
undefined,则返回undefined
逻辑或操作符也具有短路的特性。只不过对逻辑或而言,第一个操作数求值为true,第二个操作数就不会再被求值了。
流程控制-分支语句
1.1-语句与表达式
简单概括: 有运算符参与的就是表达式,没有运算符参与的就是语句
- 1.表达式 : 由运算符组成的式子, 一定会有运算结果 (运算)
- 2.语句 : 让js编译器执行某个命令,做什么事情 (执行)
- 3.分支语句 循环语句
1.2-if单分支结构
- if结构语法:
if(条件 true/false){ 条件成立时需要执行的代码 } - if结构补充说明:
- (1).大括号中可以是任何代码,不限数量
- (2).如果大括号中代码有且只有一行,则可以省略大括号。这种写法代码不规范,不是老司机的作风
3.注意点:小括号中的条件可以是哪些呢
- (1)关系表达式:结果一定是布尔类型
- (2)布尔类型的值:true和false
- (3)其他表达式和值:都会先转换成布尔类型再判断真和假
1.3-if-else if-else多分支结构
语法
if(条件1){
条件1成立时需要执行的代码
}else if(条件2){
条件2成立时需要执行的代码
}else if(条件3){
条件2成立时需要执行的代码
}
.....
else{
如果前面所有条件都不满足,则执行else代码
}
注意点
(1)多分支所有的大括号代码最多只会执行一个,只有当前面的条件不满足,才会进入后面的条件判断
(2)多分支一定要以if开头,后面else if可以多个,结尾else可以省略 -->
1.-4三元表达式
三元运算符语法
* 三元运算符: `?:`
* 三元表达式:`表达式?代码1:代码2`
* 1.如果表达式成立则执行代码1,否则执行代码2
//如果代码1 和 代码2 不能产生结果,则三元表达式的结果是undefined
let res = 1 > 0 ? alert("哈哈") : alert("呵呵");
let res = 1 > 0 ? alert("哈哈") : let res = 1 > 10 ? alert("1") : alert("2")
console.log(res); //undefined
1.5-switch-case分支结构(固定值)
let subject = +prompt(
'请输入您想要选择的学科 1-前端 2-java 3-UI 4-新媒体'
)
switch(表达式){
case 值1:
表达式的结果 === 值1,需要执行的代码
break;
case 值2:
表达式的结果 === 值2,需要执行的代码
break;
case 值3:
表达式的结果 === 值3,需要执行的代码
break;
.......
default:
表达式的结果和上面所有的case后面的值都不全等,则会执行这里的代码
break;
}
注意事项
* 1.表达式的结果要和值一定是全等的关系===
* 2.break作用:结束该switch语句,所以一般情况下要加上,如果不加上则会发生穿透
* 穿透:从上一个case代码快执行到下一个case代码快
* break关键字的作用就是防止穿透
* 3.default语句可以写在任何地方,也可以省略,但是一般写在最后,这是一种代码规范
流程控制-循环语句
1.1-while 循环
循环结构:代码重复执行
while循环语法
while( 条件 true/false ){
循环体:需要重复执行的代码
}
执行规则
1.判断条件是否成立
1.1 true : 则执行循环体代码
1.2 false : 循环结束,执行大括号后面的代码
2.重复步骤1
//例子
//1.声明变量记录循环次数(循环变量)
let num = 1;
//2.循环条件
while (num <= 10) {
console.log("班长爱坤哥")
//3.循环变量自增
num++;
}
console.log("班长完事了")
1.2-for 循环
for循环: 1.声明循环变量 2.循环条件 3.循环变量自增 写在一个小括号中,代码更加简洁易读
语法:
for(语句1;语句2;语句3){
循环体:需要重复执行的代码
}
执行规则
1. 执行语句1(声明循环变量)
2. 判断语句2结果是否成立(循环条件)
2.1 true : 执行循环体
* 2.1.1 执行语句3(循环变量自增)
2.2 false: 循环结束,执行大括号后面的代码
3. 重复步骤2
1.3-break 与 continue 关键字
continue : 结束本次循环体,立即进入下一次循环判断
* continue关键字只能用于循环语句
break: 结束整个循环语句,立即执行大括号后面的代码
* break关键字可以用于 循环语句 + switch-case
数组
1:数组的语法
- 1-1数组名 let arr=[]声明
- 1-2数组元素 元素1,元素2,[]里面的是元素
- 1-3数组取值 数组名[下标]
- 1-4数组长度 arr.length
- 1-5数组遍历 for (let i=0;i<arr.length;i++){ arr[i] }
2:数组查询
- 数组取值(查) 数组名[下标]
- 数组取值
- 如果下标存在,则获取 元素值
- 如果下标不存在,则获取 undefined
3:数组修改
- 数组赋值(改) 数组名[下标] = 值
- 数组赋值 // arr[0] = 70修改第一个元素为70
- 如果声明时没有 5,而arr[5]=70,,则新增一个元素
4:数组新增
- 数组新增有两个方法
- 数组名.push(元素) : 一个或多个元素,添加到末尾
- 数组名.unshift(元素) : 一个或多个元素,添加到开头
5:数组删除
- 数组的删除
- (1)数组名.pop:删除最后面一个元素
- (2)数组名.shift:删除最前面一个元素
- (3)数组名.splice(下标,数量):从'下标'开始删除'数量'个元素
6.数组应用
6-1数组求和
(1)声明一个变量存储结果
(2)遍历数组中每一个元素
(3)累加
function getsum(arr1) {
let sum1 = 0
for (let i = 0; i < arr1.length; i++) {
sum1 += arr1[i]
}
6.2-求数组最大元素与最小元素
(1).声明变量默认为第一个元素
(2).遍历数组
(3).依次比较大小,然后赋值
function getsum(arr) {
let sum = arr[0]
for (let i = 1; i < arr.length; i++) {
if (sum < arr[i]) {
sum = arr[i]
}
}
return sum
}
let sum1 = getsum([1, 2, 12, 23, 34, 5, 6])
console.log(sum1)
6.3-筛选数组
(1).声明空数组
(2)遍历旧数组,找出符合条件的数
(3).添加到新数组中
let arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== 0) {
newArr.push(arr[i]);
}
}
函数
1.函数的介绍
函数是一个封箱的代码块,复用时调用即可 function 函数名(){函数体}
1-1.声明函数:
声明函数只是把代码存起来,不会执行函数体
// function 函数名() {
// 函数体代码: 需要存储的一段代码
// }
1-2.调用函数 : 执行函数体代码
函数名()
2.传参
- 函数名(形参){函数体}
- 函数名(实参)
- 实参相形参传数据
3.逻辑中断
- 逻辑或|| 一真则真 找真,左边式子为true,得到左边式子的值,同理右边
- 逻辑与&& 一假则假 找假,左边式子为false,得到左边式子的值,同理右边
4.返回值
return返回函数里面的数据给调用者
- (1)return是结束函数的
- (2)return可以不给,默认值是undefined
- (3)return可以给但不赋值,则返回值也是undefined
5.函数工作原理
- (1)传参,实参给形参赋值的过程,调用者->函数
- (2)函数操作函数体
- (3)return返回值给调用者
6.开关思路
- (1)声明一个开关变量(一般默认为true)
- (2)遍历数组,判断每一个元素是否满足条件,遇到不满足修改开关 变量为false
遇到满足的不用修改,因为默认就是true
变量值 function isAllTrue(arr){
let res = true
for(let i = 0;i< arr.length;i++){
if( arr[i] < 0){
res = false break
}
}
return res
}
7.作用域
1.js变量作用域: 变量可以使用的区域
作用:避免变量污染(变量名相同导致代码冲突) s三种作用域
2.1 全局作用域(全局变量) : 在函数外面let的变量
2.2 局部作用域(局部变量) : 在函数里面let的变量
2.3 快级作用域(快级变量) : 在分支或循环大括号中let的变量
3.作用域链(就近原则,先在自己域里面的,没有就找上一级)
let num = 10//0级
function fn1(){//fn1本身还是0级的,只是里面函数体是1级
//1级
let num = 20
console.log(num)//20
function fn2(){
//2级
let num = 30
console.log(num)//30
}
fn2()
}
fn1()
console.log( num )//10 -->
8.匿名函数
- 1.匿名函数 : 没有函数名的函数
- 2.匿名函数作用 : 开辟局部作用域,避免全局变量污染
- 3.小细节: 匿名函数自执行的时候,上一个语句分号不能省略
;(function(){
let num = 10//局部变量
console.log('111')
})()
对象
1.对象介绍
- 1.对象是什么 : 对象是一种复杂数据类型
- 2.对象作用 :以键值对方式存储多个数据
- 3.对象与数组异同点
-
- 相同点:都是复杂数据类型,都可以存储多个数据
-
- 不同点: 存储方式不同 数组: 有序存储 对象: 无序存储(键值对)
2.对象语法
-
- 声明对象 let 对象名{属性名:属性值,}
-
- 取值语法 log(对象名.属性名)
注意点:对象中的属性值是什么数据类型, 取出来的时候就可以使用这个类型的所有语法
3.对象操作
- 1.查询属性:
查询对象属性两种语法
点语法 obj.属性名
[]语法 obj['属性名'] obj[ 变量名 ]
注意点: 如果[]里面有'',则解析是属性名
如果[]里面没有'',则解析是变量名
查询对象特点
如果属性名存在,则获取属性值
如果属性名不存在,则获取undefined
- 2.修改 新增(赋值)属性:
对象名.属性名 = 值
对象名['属性名'] = 值(两种写法一样)
注意点:(1)如果已经存在的属性赋值,则是修改
(2)如果不存在的属性赋值,则是新增
-
3.删除对象属性
delete 对象名.属性名
4.对象遍历
遍历对象 :
特殊的for-in循环 (专用于遍历对象)
for(let key in 对象名){
对象名[key]
}
5. 引用类型 与 值类型 区别
1.值类型(简单数据类型) : string number boolean undefined null
栈中存储数据,赋值拷贝的也是数据,修改拷贝后的数据对原数据‘没有影响’
let 只能在栈里开辟空间
2.引用类型(复杂数据类型) : array function object
[],function,{}可以开辟堆空间
栈中存储地址,数据存在堆中。赋值拷贝的是地址,修改拷贝后的数据对元素‘有影响’
在比较时,比较的是地址,而不是数值
[1,2,3]==[1,2,3] false
[1,2,3][1]==[1,2,3][1] true
js高级复习
原型对象
1.面向对象
- 面向对象:是一种只注重结果的思维方式
- 面向过程:注重过程
- 两者的关系:面向对象的本质是面向过程的一种封装
2.内置对象
1.内置对象api
- 内置对象api : js作者写好的对象的一些方法
- 内置对象 : js作者提前写好的对象,直接拿来使用即可
- api : 是预先定义的函数
2.array对象
3.string对象
4.原型对象
- 概念:当我们创建函数的时候,系统会自动帮你创建一个与之对应的对象,称之为原型对象
- 作用:解决变量污染,但是这个对象本身也会造成污染
5.原型对象关系
prototype : 属于构造函数,指向原型对象
- 作用:解决内存浪费+变量污染
proto : 属于实例对象,指向原型对象
- 作用: 实例对象 访问 原型对象的成员
constructor : 属于原型对象,指向构造函数
- 作用: 可以让实例对象知道自己是被谁创建的
(1) 构造函数
function person(name,age){
this.name=name
this.age=age
}
(2)原型对象
person.prototype=function(){
this.eat=eat
}
(3)实例对象
let p1=new person(name,age)
let p2=new person(name,age)
//检测构造函数、原型对象、实例对象三者之间关系: 两行代码
console.log(p1.__proto__.constructor === Person)
//true (你爹是你爹,你妈的老公是你爹)
console.log(p1.__proto__ === Person.prototype)
//true (你妈是你妈)
(4) 静态与实例成员
静态成员:属于函数的成员
实例成员:属于实例对象的成员
获取对象所有的属性值:
Object.value(对象名)
let obj={}
Object.value(obj)
Object.key(obj)
5. 对各种条件使用逻辑运算符
如果你想减少嵌套 if…else 或 switch case,你可以简单地使用基本的逻辑运算符AND/OR。
function doSomething(arg1){
arg1 = arg1 || 10;
// 如果尚未设置,则将 arg1 设置为 10 作为默认值
return arg1;
}
let foo = 10;
foo === 10 && doSomething();
// is the same thing as if (foo == 10) then doSomething();
// 输出: 10
foo === 5 || doSomething();
// is the same thing as if (foo != 5) then doSomething();
// 输出: 10
复制代码