JavaScripit-week2

154 阅读11分钟

数据类型转换

强制类型转换:

1、转字符串

1.xx.toString();//undefined和null不能使用,不能使用,去调用任何的属性和方法,因为他们俩不是对象。
2.String(xx);//万能的,但是没什么用:千万不要手动适应,完全等效于隐式转换,还不如+"";

2、转数字

1.parseInt(str/num)-专门用于字符串转为整数的
执行原理:从左向右依次读取每个字符,碰到非数字字符就停止,不认识小数点,一开始就碰到不认识的,则为NaN2.parseFloat(str)-专门欧阳姑娘与字符串转为浮点数的
执行原理:几乎个parseInt一致,但是认识第一个小数点
3.Number(xx);万能的,但是没什么用,完全等效于隐式转换,还不如*1 /1 -0

3、转布尔

Boolean(xx);//万能的,任何人都可以转为一个布尔值,简化版写法:!!xx-简化版也不会用。
哪些会为false? 6个:0,"",undefined,null,NaN,false。其他都为ture
注意:一定要记得那些人会为false,在循环或分支的条件判断种都会带有此隐式转换,隐式转换为布尔值
        if(Boolean(条件)){}

运算符和表达式

算术运算

+ - * / %
隐式转换:默认,转为数字再运算
特殊:
    1、+运算,只要碰上一个字符串,则变为拼接
    2、- * / %,纯数字组成的字符串,也可以转为数字,但是非纯数字的字符串转为NaN
    NaN参与任何算术运算结果仍为NaN	

比较运算

> < >= <= == != === !==
结果:布尔值
隐式转换:默认,左右两边都会悄悄的转为数字,再比较。
特殊:
    1、如果左右【两边】参与比较的都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码)不需要记忆:但是知道常识
        0-9<A-Z<a-z<汉字
        汉字:记不了,太多了,20000+个以上,汉字一定比数字和字母的都大
        百度搜索:中文字符集 Unicode 编码范围
        汉字的第一个字:一(unicode:4E00)-(ascii:19968)
        汉字的最后一个字:龥(unicode:9fa5)-(ascii:40869)
了解着玩的常识:汉字的ascii或者unicode号为什么这么大?
   
    2NaN参与任何比较运算结果都为false,带了一个问题,没有办法使用普通的比较运算判断一个xx是不是NaN
解决:!isNaN(xx); true->有效数字  false->NaN

    3undefined==0,
    问题:==区分不开undefinednull,怎么才能区分开?
    undefined===null
    全等:===,要求值和数据类型都要相同,换句话说,就是不再带有隐式转换
	 !==,不带隐式转换的不等比较
	 写一个String()方法的底层原理
         function String(x){
                    if(x===null){
                            return "null";
                          }else if(x===undefined){
                            return "undefined";
                          }else{
                            return x.toString();//return 返回
                                }
                                    }

逻辑运算符

隐式转换:悄悄的都变为布尔,然后综合比较得出结论
&&:全部的条件都为true,结果才为true
    只要有一个为false,结果才为false

||:全部的条件都为false,结果才为false
    只要有一个为true,结果九尾true

!:颠倒布尔值

特殊:用法
短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不再执行。
    &&短路:如果前一个条件为true,后一个操纵不执行
           如果前一个条件为false,后一个操作不执行
           简化了简单的分支:if(条件){操作}
    语法:条件&&(操作);
   
   ||短路:如果前一个条件为true,不需要执行后一个
           如果前一个条件为false,需要执行后一个
           使用场景:两个值二选一 - 后期做浏览器兼容性(老IE)
	   e=e||window.event; - 见小案例

位运算

    左移:m<<n,读作m左移了n位,相当于m*2的n次方
    右移:m>>n,读作m右移了n位,相当于m/2的n次方
	   缺点:底数永远只能是2

赋值运算

一句话执行了两个操作,先运算,再赋值
+= -= *= /= %= ++ --
何时使用:只要取出变量中的值,在做计算,之后还要在保存回去时,就要试用赋值运算
i+=1 或者 i++
递增:i++; 每次只能+1
累加:i+=n; 每次想加几,随便你

笔试题:++ 分为前++和后++
        1、单独使用时,没有参加别的表达式,放前放后都一样
        2、如果参与了别的表达式:
                    变量中的值都会+1
                    ++i,返回的是递增后的新值
                    i++,返回的是递增前的旧值

三目运算

简化分支:if(){}else{}	if(){}else if()else{}

语法:
    1、条件?操作1:默认操作;
    2、条件1?操作1:条件2?操作2:默认操作;

舍入误差

num.toFixed(n);//带有四舍五入的功能,并能按你传入的n保留n位小数

获取第一个字符的ascii码

var ascii=str.charCodeAt(0);

自定义Function

什么是函数:需要定义好的,可以反复执行的代码段
何时使用:1、不希望打开页面立即执行 2、以后可以反复调用 3、希望绑定在页面元素之上

创建并调用

创建

1、声明方式创建:
        function 函数名(形参,...){
                函数体;
                return 返回值/结果;
        }

2、直接量方式:
        var 函数名 = function(形参,...){
                函数体;
                return 返回值/结果;
        }

调用

var 接住返回的结果 = 函数名(实参);

//其实return的本意是退出函数,但是如果return后跟着一个数据
//顺便将数据返回到函数作用域的外部,但return只负责返回,不负责保存
//具体需不需要得到函数的结果,看你自己

声明提前

在程序正式执行之前,var声明的变量(轻)和function声明的函数(重),都会悄悄的集中定义在当前作用域的顶部,但是赋值留在原地。

声明创建的函数会完整的提前
直接量方式创建的函数不会完整提前,只有变量部分会提前

按值传递

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

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

预定义的全局函数

前辈们提前创建好的函数,我们可以直接使用,在任何位置都可以使用

编码和解码

    编码:var code = encodeURIComponent("xx")
    解码: var 原文 = decodeURIComponent(code)
  浏览器自带此功能

isFinite(num)

判断num是不是无穷大,ture->有效数字 false->无穷大
哪些会为falseNaNInfinity,分母为0

eval

eval(str):计算字符串,简单来说就是脱字符串的衣服

分支结构

switch

语法: switch(变量/表达式){
            case1:
            操作1;
            case2:
            操作2;
            default:
            默认操作
}
特殊:
    1case的比较不带隐式转换
    2、问题:默认只要一个case满足后,会将后面的操作全部做完0.
       解决:break;
.   00..建议:每一个case的操作后都跟上一个break
    3default可以省略,如果条件都不满足的情况,什么事都不会做

面试题:if vs switch
        1switch...case..缺点:必须要知道准备的结果才能使用,不能做范围判断
        2if...else..缺点:执行效率相对较低,优点:可以范围判断
        

循环结构

while

while(循环条件){循环体}

do while

do{循环体}while{循环条件}

面试题

whiledo...while的区别
只看第一次:如果第一次大家都满足,两者没有区别
           如果第一次都不满足,while一次都不执行,dowhile至少会执行一次

for

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

流程控制语句

退出循环: break;//退出整个循环
          continue;//退出本次循环

数组

基础概念:
        什么是数组:在一个内存(变量)中保存了多个数据的一个集合结构
        何时:只要存储的多个相关的数据,都要用数组集中保存
        为什么:一个好的数据结构,可以极大的提升我们程序员的开发效率

创建

1、直接量方式: var arr = [值1,...]
2、构造函数方式: var arr = new Array(值1,...)

访问

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

三大不限制

1、不限制长度
2、不限制类型
3、不限制下标越界

唯一属性

数组名.length//获取当前数组的长度
三个固定套路:
            1、末尾添加:arr[arr.length]=新值
            2、获取倒数第n个:arr[arr.length-n]
            3、删除倒数n个:arr.length-=n

遍历

对数组中每个元素执行相同或相似的操作
for(var i = 0;i<arr.length;i++){
            arr[i]//当前次元素
}

关联(hash)数组

什么是:下标是可以自定义的
为什么:索引数组的下标无具体意义,不便于查找
hash数组的length永远失效,永远为0

创建

1、创建空数组:var arr = [];
2、为数组添加下标并且添加元素:arr["自定义下标"]=新值

访问

arr["自定义下标"]

遍历

for(var i in arr){
        i;
}
for in 虽然不能定义从哪里开始,到哪里结束,专门用于遍历数组的,既可以遍历索引数组也可以遍历hash数组

原理

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

js里面的一切东西都是对象,除了undefinednull,一切对象的底层都是hash数组

数组的API

连接数组

var str = arr.join("自定义连接符");

固定套路:
         1、笔试题:将数组里面的内容拼接为一句话/单词;
            无缝拼接: var str = arr.join("");
        
         2、将数组拼接为DOM页面元素
             //数据
             var arr = ["北京","南京","西京"]
             //转为字符串,并且拼接好标签
             var str = "<开始标签>"+arr.join("</结束标签><开始标签>")+"</结束标签>"
             //渲染到DOM树上
             elem.innerHTML = str;

数组的拼接

添加元素的新方式
将你传入的实参全部拼接到arr的末尾
var newArr = arr.concat(新值)
特殊:1、不会修改原数组,只会返回一个新子数组
      2、concat支持传入数组参数,悄悄将你传入的数组打散为单个元素后再拼接

截取子数组

根据你传入的开始下标截取到结尾下标
var subArr = arr.slice(stari,endi+1)
特殊:1、不修改原数组,只会返回一个新子数组
      2、含头不含尾
      3、endi可以省略不写,会从starti位置一直截取到末尾
      4、其实两个是实参都可以省略-从头截到尾,深拷贝,和以前的按值传递(浅拷贝不同),一个修改不会影响到另一个
      5、支持负数参数,-1代表倒数第一个

以上API都是不会修改原数组的


以下API都是会修改原数组的

删除、插入、替换

删除:var dels = arr.splice(starti,n);//n代表删除的个数
特殊:其实splice也有返回值,返回的是你删除的元素组成的一个新数组

插入:arr.splice(starti,0,值1,...)
注意:1、原starti位置的元素以及后续元素都会向后移动
      2、千万不要插入一个数组,会导致我们的数组一些是一维,一些是二维

替换:var dels = arr.splice(starti,n,值1,...)
注意:删除的元素不必和插入的元素个数相同

翻转数组

arr.reverse();-以后不会使用

排序

两种方式:
    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;
            }
        }
    }
    2、正式开发中:
        arr.sort();
    问题1:默认会将元素们转为字符串,按位PK ascii码,如果希望按数字排序?
    解决:
            arr.sort(function(a,b){//回调函数
                        console.log(a);//拿到后一个
                        console.log(b);//拿到前一个
                        return a - b;//如果return返回是一个正数,说明后一个数>前一个数
                                     //如果return返回的是一个负数,说明后一个数<前一个数
                                     //如果return返回的是一个0,说明后一个数==前一个数
                                     //而我们的sort方法正好可以根据你返回的正数/负数/0来排序
            })
    
    问题2:只能升序排列,如何降序
            arr.sort(function(a,b){
                return b-a;
            })
    
    强调:排序其实非常重要,切记,只要以后页面中有排序功能,他的底层一定是一个数组,因为只有数组具有排序方法

栈和队列

添加元素和删除元素的新方法

栈:其实就是一个数组。只不过是一端封闭,只能从另一端进出的数组

何时:优先使用最新的数据,现实生活中,情况不多
如何:
        开头进:arr.unshift(新值,...);//添加元素的新方式,向前添加,缺陷:导致其余元素的下标发生改变
        开头出:var first = arr.shift();//删除元素的新方式,向前添加,缺陷:导致其余元素的下标发生改变
        结尾进:arr.push(新值,...);//添加元素的新方式,向后添加,完全等效于arr[arr.length]或者arr.concat
        结尾出:var last = arr.pop();//删除元素的新方式,向后删除

队列:其实就是数组,只不过一端进,另一端出

何时:根据先来后到的顺序,现实中多
如何:
        开头进:arr.unshift(新值,...);
        结尾出:var last = arr.pop;
        结尾进:arr.push(新值,...);
        开头出:var first = arr.shift();

拓展

周期定时器:
        开启:timer = setInterval(function(){
                操作;
        },间隔毫秒数)
        停止:clearInterval(timer)
鼠标移入:onmouseenter
鼠标移出:onmouseleava

二维数组

数组的元素,又引用着另一个数组
何时:在一个数组内,希望再次细分每个分类
创建:var arr = [[arr1],[arr2],[arr3]];
访问:arr[行下标][列下标];
特殊:列下标越界,返回undfined
      行下标越界,报错

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

String的概念

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

引用对象类型

String Number Boolean ->包装类型
Array Function Date(日期) Math(数字) RegExp(正则:验证)
Error(错误)
Object(面向对象开发方式)
Global(全局对象)

包装类型

专门将原始类型的值封装为一个引用类型的对象
为什么:原始类型的值原本是没有任何属性和方法,意味着原始类型本身是不支持操作
何时使用:只要试图用原始类型的变量调用属性或者方法时,自动包装
何时释放:方法调用完毕后,自动释放包装类型,并且返回数据

String的API

1、转义字符:\
    作用:1、将字符串中和程序冲突的字符转为原文
                "\"\""
                '\'\''
          2、包含特殊功能的符号
                换行:\n
                制表符:\t
          3、输出unicode编码的字符
                第一个汉字:\u4e00
                最后一个汉字:\u9fa5

大小写转换

何时:只要程序不区分大小写,就要先统一转为大写或者小写
如何:  大写:var upper = str.toUpperCase();
        小写: var lower = str.toLowerCase();

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

var newStr = str.charAt(i) === str[i]

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

var ascii = str.charCode(i)

根据ascii码转回原文

var 原文 = String.fromCharCode(ascii);

检索字符串

检查索引,获取关键字的下标
var i = str.indexOf("关键字",starti);
从starti位置开始,查找右侧第一个关键字的位置
starti可以省略,默认从0位置开始查找
返回值:找到,返回的是第一个关键字的第一个字符的下标
      没找到,返回-1,
作用:判断有没有
强调:数组也能用此方法

截取字符串

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

拼接字符串

var newStr = str.concat(str1,...)//还不如+运算

替换字符串

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

切割字符串

作用:将字符串转为数组
var arr = str.split("自定义切割符");
特殊:1、切割后,切割符就不存在
     2、切割符"",切散每个字符

拓展

创建空元素

var elem = document.createElement("标签名");

为此空标签添加必要的属性或者事件

elem.innerHTML = "内容";
elem.属性名 = "属性值";
elem.on时间名 = function(){};

渲染到DOM树上

父元素.appendChild(新元素)

小案例

获取四位随机数

   var arr = [],
        code = "";
      function f1(a, b) {
        for (var i = a; i <= b; i++) {
          arr.push(String.fromCharCode(i));
        }
      }
      f1(48, 57);
      f1(65, 90);
      f1(97, 122);
      console.log(arr);

      while (code.length < 4) {
        var a= parseInt(Math.random() * arr.length);
        if(code.indexOf(a)==-1){
            code+=arr[a];
        }
      }
      var user= prompt("请输入验证码"+ code);
      (user.toUpperCase()==code.toUpperCase())?alert("验证成功"):alert("验证失败");

根据数据渲染表格

      var str = "tom@补给兵@60%#mary@医疗包@80%#john@特种兵@100%";
      var table = document.createElement("table");
      var newstr = str.split("#");
      var arr = ["姓名", "兵种", "血量"];
      var tr = document.createElement("tr");
      for (var i = 0; i < arr.length; i++) {
        var td = document.createElement("td");
        td.innerHTML = arr[i];
		tr.appendChild(td);
      }
	  table.appendChild(tr);
      for (var i = 0; i < newstr.length; i++) {
        var tr = document.createElement("tr");
        var newstr1 = newstr[i].split("@");
        for (var j = 0; j < newstr1.length; j++) {
          var td = document.createElement("td");
          td.innerHTML = newstr1[j];
          tr.appendChild(td);
        }
        table.appendChild(tr);
      }
      bd.appendChild(table);

淡入淡出轮播图-未封装版

  var btn = document.getElementsByTagName("button"),
        img = document.getElementsByTagName("img"),
        li = document.getElementsByTagName("li"),
        j = 0,
        cal = document.getElementsByClassName("carousel")[0];
		console.log(cal)
      for (i in btn) {
        btn[i].onclick = function () {
          if (this.innerText == ">") {
            j++;
            j == li.length && (j = 0);
            for (var i = 0; i < li.length; i++) {
              img[i].className = " ";
              li[i].className = " ";
            }
            img[j].className = "active";
            li[j].className = "active";
          } else {
            j--;
            j == -1 && (j = li.length - 1);
            for (var i = 0; i < li.length; i++) {
              img[i].className = " ";
              li[i].className = " ";
            }
            img[j].className = "active";
            li[j].className = "active";
          }
        };
      }
      time = setInterval(function () {
        j++;
        j == li.length && (j = 0);
        for (var i = 0; i < li.length; i++) {
          img[i].className = " ";
          li[i].className = " ";
        }
        img[j].className = "active";
        li[j].className = "active";
      }, 2000);

淡入淡出轮播图-封装版

	<body>
		<div class="carousel">
			<div class="carousel_img">
				<img class="active" src="../images/1.jpg" />
				<img src="../images/2.jpg" />
				<img src="../images/3.jpg" />
			</div>
			<img src="../images/3.jpg" />
			<button><</button>
			<button>></button>
			<ul>
				<li dy="0" class="active"></li>
				<li dy="1"></li>
				<li dy="2"></li>
			</ul>
		</div>

		<script type="text/javascript">
			var btns = document.getElementsByTagName("button"),
				imgs = document.getElementsByTagName("img"), //[img,img,img,img]
				lis = document.getElementsByTagName("li"), //[li,li,li]
				car = document.getElementsByClassName("carousel")[0], //[li,li,li]
				j = 0; //计数器
			for(var i in btns) {
				btns[i].onclick = function() {
					if(this.innerText == ">") {
						animate(1);
					} else {
						animate(-1);
					}
				}
			}
			for(var i in lis) {
				lis[i].onclick = function() {
					animate(0,this);
				}
			}
			timer = setInterval(function() {
				animate(1);
			}, 1000)
			car.onmouseenter = function() {
				clearInterval(timer);
			}
			car.onmouseleave = function() {
				timer = setInterval(function() {
					animate(1);
				}, 1000)
			}
		function animate(num,li) {//num==0 li==this
				if(num){
					j+=num;
					if(j==lis.length){j=0}else if(j==-1){j=lis.length-1}					
				}else{
					j=parseInt(li.getAttribute("dy"));
				}

				
				for(var i = 0; i < lis.length; i++) {
					lis[i].className = "";
					imgs[i].className = "";
				}
				imgs[j].className = "active";
				lis[j].className = "active";
			}
		</script>
	</body>

二级联动

      var arr = ["-请选择-", "北京", "南京", "西京", "东京", "重庆"];
      var arr1 = [
        ["-请选择-"],
        ["天安门", "玄武门", "朝阳"],
        ["南京1", "南京2", "南京3"],
        ["西京1", "西京2", "西京3"],
        ["东京1", "东京2", "东京3"],
        ["重庆1", "重庆2", "重庆3"],
      ];
      sel.innerHTML = "<option>" + arr.join("</option><option>") + "</option>";
      sel.onchange = function () {
        var i = this.selectedIndex;
        var newarr1 = arr1[i];
        sel1.innerHTML =
          "<option>" + newarr1.join("</option><option>") + "</option>";
      };
      sel.onchange();

购物车-封装版

<!DOCTYPE html>
<html>
  <head>
    <title>new document</title>
    <meta charset="utf-8" />
  </head>

  <body>
    <table id="tbl">
      <thead></thead>
      <tbody>
        <tr>
          <td>iphone6</td>
          <td>4488</td>
          <td>
            <button>-</button>
            <span>1</span>
            <button>+</button>
          </td>
          <td>4488</td>
        </tr>
        <tr>
          <td>iphone7</td>
          <td>5488</td>
          <td>
            <button>-</button>
            <span>1</span>
            <button>+</button>
          </td>
          <td>5488</td>
        </tr>
        <tr>
          <td>iphone8</td>
          <td>6488</td>
          <td>
            <button>-</button>
            <span>1</span>
            <button>+</button>
          </td>
          <td>6488</td>
        </tr>
        <tr>
          <td>RTX 3090</td>
          <td>20000</td>
          <td>
            <button>-</button>
            <span>1</span>
            <button>+</button>
          </td>
          <td>20000</td>
        </tr>
        <tr>
          <td>RTX 3080</td>
          <td>16000</td>
          <td>
            <button>-</button>
            <span>1</span>
            <button>+</button>
          </td>
          <td>16000</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td colspan="3">总计:</td>
          <td id="total">0</td>
        </tr>
      </tfoot>
    </table>

    <script type="text/javascript">
      var btn = document.getElementsByTagName("button");
      var total = document.getElementById("total");
      for (var i = 0; i < btn.length; i++) {
        btn[i].onclick = function () {
          if (this.innerText == "+") {
           cacl(1,this)
          } else {
            cacl(-1, this);
          }
          moneytotal();
        };
      }
      moneytotal();

      function moneytotal() {
        var tbody = document.getElementsByTagName("tbody")[0];
        var trs = tbody.children;
        for (var i = 0, sum = 0; i < trs.length; i++) {
          sum += parseInt(trs[i].lastElementChild.innerText);
        }
        total.innerHTML = sum;
      }
      function cacl(num, btn) {
        if (num == 1) {
          var span = btn.previousElementSibling;
        } else {
          var span = btn.nextElementSibling;
        }
        var jia = parseInt(span.innerText) + num;
        span.innerHTML = jia;
        var price = btn.parentNode.previousElementSibling;
        var up = parseInt(price.innerHTML);
        var money = btn.parentNode.nextElementSibling;
        var money1 = parseInt(money.innerText);
        money.innerHTML = jia * up;
      }
    </script>
  </body>
</html>