学习JavaScript的第二周

138 阅读9分钟

数据类型的转换

页面上的数据类型都是字符串,需先转换再操作

强制类型转换:

  1. 转字符串
  • 1、xx.toString();->undefined和null不能使用
  • 2、String();一般来说不使用,等效于隐式转换
  1. 转数字
  • 1、parseInt(str/num);->将字符串转为整数
  • 2、parseFloat(str);->将字符串转为浮点数(小数)
  • 3、Number();->一般来说不使用,等效于隐式转换
  1. 转布尔值
  • Boolean(xx);->万能的,任何人都可以转为一个布尔值,简化版写法:!!xx 注:0,"",undefined,null,NaN,false,这6个结果为false,其余的都为true

隐式转换:一般在运算符之中

  1. 运算符和表达式
  • 算术运算:+ - * / % 隐式转换:默认转为数字,在运算
  • 特殊:
  1. +运算,只要碰上一个字符串,则变为拼接
  2. -,*,/,%纯数字组成的字符串,也可以转为数字,但是非纯数字的字符串转为NaN,NaN参与任何算术运算结果仍为NaN。
  • 比较运算:> < >= <= == != === !== 隐式转换:默认,左右两边都会悄悄的转为数字,再比较。
  • 结果:布尔值
  • 特殊:
  1. 如果左右【两边】参与比较的都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码)
  2. NaN参与任何比较运算结果都为false。
  3. ==区分不开undefined和null,需要用到全等:===,要求值和数据类型都要相同,不再带有隐式转换,!==,不带隐式转换的不等比较
  • String()方法的底层原理
    function String(x){
	if(x===null){
	return "null";}
        else if(x===undefined){
	return "undefined";}
        else{
	return x.toString();
		     }
		   }
  • 逻辑运算符: 隐式转换:转为布尔,然后比较得出结论
  • &&:全部的条件都为true,结果才为true,只要有一个为false,结果就为false。
  • ||:全部的条件都为false,结果才为false,只要有一个为true,结果就为true
  • !:颠倒布尔值 3.短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不再执行。
  1. &&短路:如果前一个条件为true,后一个操作才执行。如果前一个条件为false,后一个操作不执行
  • 语法:条件&&(操作);
  1. ||短路:如果前一个条件为true,不需要执行后一个,如果前一个条件为false,需要执行后一个
  • 位运算
  1. 左移:m<<n,m左移了n位,m*2的n次方
  2. 右移:m>>n,m右移了n位,m/2的n次方
  • 赋值运算:一句话执行了两个操作,先运算,再赋值:+= -= *= /= %= ++ --
  1. 使用:取出变量中的值,在做计算,之后还要在保存回去。 语法:i+=1/i++/i+=n
  • 笔试题:++ 分为 ++i 和 i++
  1. 单独使用时,没有参与别的表达式,放前放后都一样
  2. 如果参与了别的表达式:变量中的值其实都会+1,++i,返回的是递增后的新值,i++,返回的是递增前的旧值。
  • 三目运算:简化if(){}else{} 语法:条件?操作1:默认操作;/条件1?操作1:条件2?操作2:默认操作;

  • 舍入误差 语法:parseFloat(num.toFixed(n))

自定义function

  1. 使用:1、不希望打开页面立刻执行 2、以后可以反复使用 3、希望绑定在页面元素之上
    1. 创建并调用函数:
  • 创建
  1. 声明方式创建函数
function 函数名(形参,...){
		函数体;
		return 返回值/结果;
			   }

2.直接量方式创建函数

var 函数名=function 函数名(形参,...){
		函数体;
		return 返回值/结果;
			   }
  • 调用函数 语法:var 接住返回的结果=函数名(实参,...);
  1. 注:其实return的本意退出函数,但是如果return后跟着一个数据,顺便将数据返回到函数作用域的外部,但return只负责返回,不负责保存,就算省略return,默认也会return undefined,具体需不要得到函数的结果,看你自己。
  2. 作用域
  • 全局作用域:全局变量 和 全局函数,在页面的任何一个位置都可以使用
  • 函数/局部作用域:局部变量 和 局部函数,在当前函数调用时内部可用
  1. 变量的使用规则:优先使用自己的,自己没有找全局,全局没有报错
  2. 特殊:1、千万不要再函数中对着未声明的变量直接赋值会造成全局污染。2、局部可以用全局的,但是全局不能用局部的。解决方法:return 三. 声明提前:在程序正式执行之前,将var声明的变量(轻)和function声明的函数(重)集中定义在当前作用域的顶部,但是赋值留在原地。
  • 声明方式创建的函数会完整的提前

  • 直接量方式创建的函数不会完整提前,只有变量部分会提前 四、按值传递:两个变量之间进行赋值:

  • 如果传递的是原始类型的值:修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对方。

  • 如果传递的是引用类型的对象:修改一个变量,另一个变量是会受到影响的,因为大家操作其实是同一个地址值。

预定义的全局函数

  1. 定义:前辈们提前创建好的方法,我们程序员可以直接使用,在任何位置都可以使用
  • 编码和解码:url中不允许出现多字节字符,如果出现会乱码,发送前,前端将多字符原文编码为单字节字符,发送后,后端将单字节字符解码为多字节原文 语法:编码:var code=encodeURIComponent("文字"); 语法:解码:var 原文=decodeURIComponent(code);

  • isFinite(num):判断num是不是无穷大,true->有效数字 false->无穷大 注:NaN,Infinity,分母为0结果为false

  • parseInt/Float、isNaN、eval(str):计算字符串

分支结构:if分支和switch分支

语法:switch(变量/表达式){
		case1:
		操作1;
		case2:
		操作2;
		default:
		默认操作;
	}
  • 特殊:
  1. case的比较不带隐式转换
  2. 默认只要一个case满足后,会将后面所有的操作全部做完,解决:break;建议每一个case的操作后都跟上一个break;但是最后的一个操作default可以省略,如果中间多个条件,做的操作是一样的,也可以省略break;
  3. default可以省略,如果条件都不满足的情况,什么事都不会做
  • 面试题:if vs switch
  1. switch...case... 缺点:必须要知道准备的结果才能使用,不能做范围判断。 好处:执行效率相对较高
  2. if...else 缺点:执行效率相对较低。优点:可以是范围判断

循环结构

1.while循环

while(循环条件){循环体}
  1. do while循环:dowhile至少会执行一次
do{循环体}while(循环条件)

3.for循环

for(循环变量;循环条件;变量的变化){
		循环体;
	 }

4.流程控制语句:

  • 退出循环:break;
  • continue;退出本次循环

数组的基础

一. 概念:在一个内存(变量)中保存了多个数据的一个集合结构

  1. 使用:只要存储的多个相关的数据,都要用数组集中保存;

二. 创建:

  1. 直接量:var arr=[值1,...];

  2. 构造函数:var arr=new Array(值1,...);

  3. 访问:数组名[下标];

  4. 添加/修改:数组名[下标]=新值; 特殊:读取元素,下标越界 -- 返回undefined,添加元素,下标越界 -- 下标不在连续,导致变成一个稀疏数组

  5. 数组的三大不限制:1、不限制长度 2、不限制类型 3、不限制下标越界

  6. 数组唯一的属性:数组名.length:获取当此数组的长度

  • 三个固定套路:
  1. 末尾添加:arr[arr.length]=新值;
  2. 获取倒数第n个:arr[arr.length-n];
  3. 删除倒数n个:arr.length-=n ``
  4. 遍历数组:对数组中每个元素执行相同 或 相似的操作
for(var i=0;i<arr.length;i++){
			arr[i];//当前次元素
		}

  1. 如何释放一个引用类型:请你看清楚你的这个引用类型的数据有几个变量引用着,都要释放后才会真正释放,函数中的变量会自动释放。
  2. 关联(hash)数组:下标是可以自定义的
  • 使用:
  1. 创建: 1、创建空数组var arr=[]; 2、为数组添加下标并且添加元素arr["自定义下标"]=新值;

2.访问元素 arr["自定义下标"]

  1. 强调:hash数组length永远失效,永远为0!
  2. 遍历hash数组
for(var i in arr){
		i;//
		  }

5.hash数组的原理:

  • hash算法:将字符串,计算出一个尽量不重复的数字(地址值),字符串内容相同,则计算出来的数字也一定是相同的
  • 添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到这个地址之中
  • 获取元素:将指定的自定义下标交给hash算法,得到一个和当初保存时一样的数字(地址值),通过地址就找到当前保存的数据

6.js里面的一切东西都是对象,除了undefined和null,一切对象的底层都是hash数组

数组的API

  1. arr to string:转字符串 var str=arr.join("自定义连接符");
  • 固定套路:
  1. 将数组里面的内容拼接为一句话/单词; 无缝拼接:var str=arr.join("");

  2. 将数组拼接为DOM页面元素

     //数据
var arr=["北京","南京","西京","东京","重庆"]
    //转为字符串,并且拼接好标签
var str="<开始>"+arr.join("</结束><开始>")+"</结束>";
   //渲染到DOM树上
elem.innerHTML=str;

2.数组拼接:添加元素的方式 :把你传入的实参全部拼接到arr的末尾。

var newArr=arr.concat(新值1,...)

特殊:

  1. 不修改原数组,只会返回一个新数组

  2. concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素后在拼接

  3. 截取子数组:根据你传入的开始下标截取到结尾下标

var subArr=arr.slice(starti,endi+1);

特殊:

  1. 不修改原数组,只会返回一个新子数组
  2. 含头不含尾
  3. endi可以省略不写,会从starti位置一直截取到末尾
  4. 其实两个实参都可以省略 - 从头截到尾,深拷贝,和以前的按值传递(浅拷贝)不同,一个修改不会影响到另一个
  5. 支持负数参数,-1代表倒数第一个 ``
  6. 删除、插入、替换:arr.length-=n

删除:var dels=arr.splice(starti,n);//n代表删除的个数

插入:arr.splice(starti,0,值1,...);

替换:var dels=arr.splice(starti,n,值1,...);

  1. 翻转数组

语法:arr.reverse();

Array API:

  1. 排序
  • 冒泡排序
for(var j=1;j<arr.length;j++){
				for(var i=0;i<arr.length-j;i++){
					if(arr[i]>arr[i+1]){
						var middle=arr[i];
						arr[i]=arr[i+1];
						arr[i+1]=middle;
					}
				}
			}
  • 排序的API arr.sort();
  • 按数字排序
arr.sort(function(a,b){//回调函数
//	console.log(a);//拿到后一个
//	console.log(b);//拿到前一个
	return a-b;//如果return 返回是一个正数,说明后一个数>前一个数
 //如果return 返回是一个负数,说明后一个数<前一个数
 //如果return 返回是一个0,说明后一个数==前一个数
 //而我们的sort方法正好可以根据你返回的正数/负数/0来进行排序
				});

  1. 栈和队列:添加元素和删除元素的新方法
  • 栈:其实就是数组,只不过是一端封闭,只能从另一端进出的数组
  • 开头进:向前添加,缺陷:导致其余元素的下标发生改变 arr.unshift(新值,...);
  • 开头出:向前删除,缺陷:导致其余元素的下标发生改变 var first=arr.shift();
  • 结尾进arr.push(新值,...);
  • 结尾出var last=arr.pop();
  • 队列:其实就是数组,只不过是一端进,另一端出
  • 开头进 arr.unshift(新值,...);
  • 结尾出var last=arr.pop();
  • 结尾进 arr.push(新值,...);
  • 开头出 var first=arr.shift();

二维数组

数组的元素,又引用着另一个数组

1.创建

var arr=[["张三丰",128,5500],];
  1. 访问

arr[行下标][列下表];

  1. 遍历二维数组:两层循环,外层循环控制行,内层循环控制列
for(var r=0;r<arr.length;r++){
	for(var c=0;c<arr[r].length;c++){
	console.log(arr[r][c])
		}
		 }

String

  1. 什么是字符串:多个字符组成的只读字数组
  2. 和数组有相同的地方:1、字符串中的个数:str.length 2、获取字符串中某个字符:str[i] 3、遍历字符串 4、所有数组不修改原数组的API,字符串也可以使用(concat、slice)
  3. 和数组也有很多不同的地方:所有的数组直接修改原数组的API,字符串都不可以使用,比如排序只有数组可以使用,但是字符串也有很多很多属于自己的API,明天学了你就知道了

引用/对象类型

  • String Number Boolean -> 包装类型
  • Array *Function Date(日期) Math(数学) *RegExp
  • Error(错误)
  • Object(面向对象开发方式)
  • Global(全局对象) - 在浏览器中被window全局对象(保存全局变量和全局函数)代替了,只不过window可以省略不写
  1. 包装类型:专门将原始类型的值封装为一个引用类型的对象
  2. 为什么:原始类型的值原本是没有任何属性和方法,意味着原始类型本身是不支持.操作,字符串经常会被我们程序员所操作, 为了方便我们程序员为这三个人提供了包装类型(提供属性和方法)
  3. 使用:只要试图用原始类型的变量调用属性或者方法时,自动包装
  4. 释放:方法调用完毕后,自动释放包装类型,并且返回数据(又变回了原始类型)
  5. null和undefined不能使用. 因为没有包装类型

String API

  1. 转义字符:
    作用:将字符串中和程序冲突的字符转为原文

语法:"\"" '\''

  1. 包含特殊功能的符号

语法:换行:\n 制表符:\t -> 大空格tab

  1. 输出unicode编码的字符

语法:\uXXXX

  1. 大小写转换:将字符串中的每个英文字母统一的转为大写 或 小写。
  • 作用:只要程序不区分大小写,就要【先统一】转为大写 或 小写,再比较(验证码)

语法:大写:var upper=str.toUpperCase(); 小写:var lower=str.toLowerCase();

  1. 获取字符串中指定位置的字符

语法:var newStr=str.charAt(i); === str[i]

  1. 获取字符串中指定位置的字符的ASCII码

语法:var ascii=str.charCodeAt(i);

  1. 根据ascii码转回原文:

语法:var 原文=String.fromCharCode(ascii);

  1. 检索字符串:检查索引:获取关键字的下标

语法:var i=str.indexOf("关键字",starti); 从starti位置开始,查找右侧【第一个关键字】的位置,starti可以省略,默认从0位置开始查找

  • 返回值:找到,返回的是第一个关键字的第一个字符的下标 没找到,返回-1,我们不关心下标为多少,只关心为不为-1
  • 作用:判断有没有
  • 强调:数组也能用此方法,后期才添加上的
  • 获取所有关键字的下标
var str="no zuo no die no can no bibi";
var index=-1;
while((index=str.indexOf("no",index+1))!=-1){
console.log(index);
			}
  1. 截取字符串

语法:var subStr=*str/arr.slice(starti,endi+1)和数组用法一样,支持负数参数,-n代表倒数第n个/ str.substring(starti,endi+1)用法几乎和slice相同,不支持负数参数/str.substr(starti,n)支持负数参数,n代表截取的个数,不必考虑含头不含尾

  1. 拼接字符串

语法:var newStr=str.concat(str1,...)

  1. 替换字符串

语法:var newStr=str.replace("关键字"/正则,"新内容");

  1. 切割/分割字符串

语法:var arr=str.split("自定义切割符"); 特殊:1、切割后,切割符就不存在 2、切割符"",切散每一个字符