# biji13 **Repository Path**: wangdawei0418/biji13 ## Basic Information - **Project Name**: biji13 - **Description**: No description available - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-01-18 - **Last Updated**: 2021-03-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 13班笔记 ###### Javascript是一个脚本语言,作为网页的行为层。 ###### js的引入方式 * 内部引入:使用script标签,在script标签中写js代码; * 外部引入:使用script的src属性,引入一个外部的.js文件; * 行内引入 ###### 如果哪一个script标签作为引入外部文件来使用了,那么浏览器会忽略掉所有改标签内部的js代码 ###### 暂且需要记住的测试方法: * `console.log(exp)` 向控制台输出exp表达式的返回值 * `alert(exp)` 向警告框输出exp表达式的返回值 * `document.write(exp)` 向页面输出exp表达式的返回值 ###### 变量:存储数据的容器 ```javascript var 变量名 = 值; // 声明了一个变量a 里面存了一个1 var a = 1; // 如果声明过变量a,那么以后a就代表1 a // 变量声明之后还可以被重新赋值 a = 2; // 因为重新赋值了a,所以此时a的值就为2 a // 声明了变量m,但没有为其赋值,此时m里面存储的是一个undefined var m; ``` ###### 标识符:变量名,函数名和对象的属性名的命名规则; * 由字母,数字,_和$组成; * 数字不能作为开头; * 大小写敏感。 ###### !!表达式和返回值:一切有返回值(计算结果)的语句都是表达式,反之同理。 ###### 运算符:将简单表达式组合成复杂表达式的方法。 ###### !!数据类型 * Number(数字): 1,2,3,4,-1,-2,-3,1.2,3.14,Infinity(无穷大),-Infinity(无穷小),NaN(非数字) * String(字符串): "a","abc","王大a伟",""(空字符串),"1a2b3c","true","dfs&*^$" * Boolean(布尔值):true,false * undefined(未定义,空值):undefined * function(函数) * Object(对象) ###### 绑定事件 ```javascript 元素的id.onclick = function(){ // 用户点击了元素之后再执行的代码段 .... .... .... } ``` ###### 获取用户在文本框中输入的内容: ` 文本框id.value ` ###### 将字符串的数字转换为Number类型的数字 * Number("123") * parseInt("123") 有取整操作 ###### !!表达式的副作用:如果某个表达式它的存在与否会对接下来的程序造成影响,那么这个表达式就是一个有副作用的表达式。 ###### !!数据的类型的转换规则 ```javascript // 转换方法 Number(exp) Boolean(exp) String(exp) ``` * String转换为Number:除了纯数字,Infinity和-Infinity之外所有字符串的转换结果都为NaN。 * Boolean转换为Number:true为1,false为0。 * 其他类型转换为String类型,直接以字面量的形式进行转换。 * Number类型转换Boolean:除了0和NaN以外都是true。 * String转换为Boolean:除了空字符串以外,都为true * undefined,null转Boolean为false;空对象和空函数转Boolean都为true. ###### 判断的特殊情况 ```javascript NaN === NaN -> false NaN == NaN -> false undefined == null -> true undefined === null -> false 2 == true -> false ``` ###### if语句(分支语句,条件语句,逻辑语句,判断语句) ```javascript if(exp){ 语句块 } --------------- if(exp){ 语句块1 } else{ 语句块2 } ``` ###### for语句 ```javascript // 最常见的for语句形式 for(var i = 0; i < 100;i++){ console.log(i) } ``` ###### 如果一定要判断一个表达式的返回值是不是NaN ` isNaN(exp) -> Boolean ` ###### !!强化FOR语句的应用 ###### while语句 ```javascript while(exp){ // 循环体 } ``` ###### Math.pow(num1,num2):返回num1的num2次方。 ###### break和continue:只在循环语句中才可以生效;其中break也可以出现在switch语句中。做流程控制,可以提前结束本次循环或整个循环。 ###### switch语句:如果case中不带break关键字就含有了穿透特性,可以执行多个分支。 ```javascript switch(n){ case 1:{ // 代码段 console.log(1) break; } case 2:{ // 代码段 console.log(2) break; } case 3:{ // 代码段 console.log(3) break; } case 4:{ // 代码段 console.log(4) break; } default:{ // 代码段 console.log("default") } } ``` ###### 函数:一段可以被高度复用的代码段。 ```javascript // 声明函数:声明式 // 声明式特点就是在声明之前调用也可以 function 函数名(形参1,形参2...){ // 函数体 } // 声明函数:赋值式 // 赋值式特点就是在声明之前不可以调用,否则会报错 var 函数名 = function (形参1,形参2...){ // 函数体 } // 调用函数 函数名(实参1,实参2...) ``` ###### 形参:就是在函数体内部声明的变量,只声明没赋值; ###### 实参:为形参那个变量赋值(在本次调用生效) ###### 实参个数和形参个数不统一时 ``` javascript function fn(num1,num2){ alert(num1+num2) } // 在实参数量大于形参数量时,程序会忽略掉多余的实参。 fn(1,5,3) function add(num1,num2,num3){ // alert(num1 + num2 + num3) console.log(num1) console.log(num2) console.log(num3) } // 在形参数量大于实参数量时,未被赋值的形参代入到函数体内部时里面的值是undefined。 add(1,5) ``` ###### !!!return ```javascript function add(num1,num2){ alert(1) // 返回num1+num2的和,返回到调用函数表达时的返回值上去了。 return num1 + num2; // 不会执行 因为它在return语句下面 alert(2) } // 因为return语句的存在,所以此时在控制台内输出的是11而非undefined console.log(add(5,6)) ``` ###### !!调用没有return语句的函数,该调用函数表达式的返回值一定是undefined。(构造函数除外) ###### return语句的特性 * 控制调用函数表达式的返回值:如果函数体内部有return语句,那么调用该函数的表达式的返回值一定是return语句后面表达式的返回值。 * 做流程控制:当程序运行到return语句时,程序会忽略掉return语句下面所有函数体内部的代码; ###### !函数的引用 ```javascript function fn(){ alert(1) } // 调用函数 // 1)执行函数体内部的所有的代码 // 2)有一个返回值,该返回值是取决于函数体内部的return语句; // fn() // 如果只写函数,该表达式并不会调用函数体内部所有的代码 // 该表达式的返回值不取决于函数体内部的return语句,而一律返回函数自身(函数的引用) console.log(fn) // 函数的引用也是和Number,String..一样作为一个数据 // 同样也可以被放置到另外的一个变量里 // 因为函数的引用后面加一对()就代表调用该函数 // 又因为m此时返回的就是fn的引用 // 所以m()就等价于fn()等价于调用了fn函数。 var m = fn; console.log(m()) ``` ###### IIFE和匿名函数 ```javascipt // 匿名函数:没有名字的函数 function(num1,num2){ return num1 + num2 } // IIFE:自调用函数:生出来就被调用的函数 var a = (function(num1,num2){ return num1 + num2 })(1,5) console.log(a) ``` ###### !!!!变量作用域 * 全局变量:在函数体外面声明的变量;在任何地方都可以被访问到; * 局部变量:在函数体内部声明的变量;只能在该函数体内部或内层函数作用域下才能被访问到。 ###### 当局部变量和全局变量发生冲突的时候规则:以局部作用域为准; ###### 在局部作用域(函数中)声明全局变量:如果去掉var关键字,那么在函数体内部声明的变量也是全局变量。 ```javascript var a = 5; for(var i = 0 ; i < 10;i++){ // 可以被访问到,因为是全局变量 console.log(a) var b = 5; } // 可以被访问到,因为是全局变量 console.log(b) // 可以被访问到,因为是全局变量 console.log(i) // 全局变量 var quanju = 10; function fn(){ console.log(quanju) // 局部变量 var jubu = 5; (function(){ // 能访问到 console.log(jubu) var neibu = 20; })() // 不能访问到:因为外层作用域不能访问内层作用域里面的变量 console.log(neibu) } fn() // 在任何情况下,访问一个未被声明过的变量程序都会报错 // 报错的错误:xxxxx is not defined // 报错:因为在全局作用域下访问了一个局部变量。 console.log(jubu) var a = 5; function fn(){ var a = 10; // a为10:当局部作用域和全局作用域变量发生冲突时,以局部作用域为准。 console.log(a) } fn() // 5 console.log(a) function fn(){ // 变量a就是全局变量 // 如果去掉var关键字,那么在函数体内部声明的变量也是全局变量 a = 5; } fn() console.log(a) ``` ###### !变量提升:JS解释器的一种机制;js在调用某个函数的时候或在全局作用域下,会将该函数中的所有的局部变量遍历一遍,并把这些局部变量放置在函数体顶端先声明但不赋值。 ```javascript function fn(){ // a 是undefined不是报错 // 因为a是局部变量,参与变量提升操作 console.log(a) // b 会报错 因为不是局部变量,不参与变量提升操作 console.log(b) var a = 5; b = 10; } fn() // 全局作用域也会参与变量提升操作 console.log(a) var a = 5; var a = 5; function fn(){ // a为undefined,因为变量提升的操作覆盖了全局变量a的值 console.log(a) var a = 10; } fn() ``` ###### 递归:函数中调用自身。 * 初始化 * 递增/递减关系 * 程序出口(判断条件) ```javascript // 1.初始化 var i = 0; function fn(){ // 递增/递减关系 console.log(i++) // 程序出口 if(i > 5){ return; } fn() } fn() ``` ###### arguments参数对象:当声明函数时不确定调用函数者会传入多少个实参的时候,就会用arguments对象来代替形参。arguments本质上是一个类数组 ```javascript // 提取第一个元素 arguments[0] // 返回实参的个数 arguments.length ``` ###### 类数组:像是数组又不是真实数组,和数组的区别就是不含有Array.prototype也就是不含有数组的原型方法。含有数组的下标特性和.length特性。 ###### 数组:数据得到有序集合。 ```javascript // 声明空数组 var arr = [] var 声明一个含有元素的数组 var arr = [1,5,6,3,"王大伟",true] // 数组下标的特性:Array[下标] 从数据集合中提取出来某一个元素 console.log(arr[4]) // 数组.length特性:Array.length 返回数组的长度(元素的个数) console.log(arr.length) // 修改元素 arr[4] = "王小伟"; // 在数组的末尾添加 arr[arr.length] = "杨宁宁"; arr[arr.length] = "嘻嘻"; arr[arr.length] = "大黄"; ``` ###### !!循环数据,枚举数组,遍历数组 ```javascript for(var i = 0; i < arr.length;i++){ console.log(arr[i]) } ``` ###### !!数组的全局方法:`Array.方法名()` * 往后插 Array.push(新元素) * 往前插 Array.unshift(新元素) * 删除/添加 Array.splice(起始位置,被删除的数量,新增的元素) * 删除开头的 Array.shift() * 删除最后一位 Array.pop() * 颠倒数组 Array.reverse() * 数组拼接 Array.concat() * 将数组转换为字符串 Array.join(分隔符) * 切割数组 Array.slice(起始下标,终止下标) ###### !!字符串的全局方法:` String.方法名() ` * 根据下标返回字符 charAt() * 字符串拼接 concat() * 根据字符找下标 indexOf() lastIndexOf() * 替换字符 replace() 如果要全局匹配 `String.replace(/被替换字符/g,替换的新字符)` * 根据起始和终止下标切割字符串 slice() substring() * 根据起始位置和个数切割字符串 substr() * 根据字符将字符串切割成长度若干的数字 split() ###### 获取0-1之间的随机数(结果可能包含0但不包含1):`Math.random()` * 0-99的随机整数:`parseInt(Math.random()*100)` * 10-99的随机整数:` parseInt(Math.random()*90) + 10 ` ###### 对象:属性的无序集合。 ```javascript // 声明对象 var o = { name:"王大伟", sex:"male", age:27, married:false, students:["康磊","樊鲜鹏","黄嘉鹏","康佳涛","陈佳怡"], // 对象中的方法:如果哪个属性的属性值是一个函数,那么一般来说我们喜欢叫这个属性为方法。 sayHello:function(){ alert("hello") } } o.sayHello() // 读取属性 // console.log(o.sex) // console.log(o["sex"]) // 添加/修改 // o.city = "朝阳"; // o["age"] = 28; // 对象属性的删除 // delete o.students // 对象的枚举(遍历,循环) // for(var key in o){ // 遍历属性名 // console.log(key) // 遍历属性值 // console.log(o[key]) // } // 对象的检测 检测对象中含不含有某一条属性 console.log("age" in o) console.log("kjsdfhjkadhj" in o) ``` ###### !!引用类型和原始类型 ```javascript var a = 5; var b = a; a++ console.log(a) //6 console.log(b) //5 因为原始类型的值是存放在堆中的,所以将原始类型的变量赋值给另外的一个变量相当于是值的拷贝。 var obj = {name:"王大伟",age:27}; var obj2 = obj; obj.age++; console.log(obj.age) // 28 console.log(obj2.age) // 28 因为引用类型的值是存放在栈中的,变量里面存储的只是指向栈中的一个指针,所以在将引用类型的变量赋值给另外的一个变量是相当于是将指针赋值给了另外的一个变量,实体只有一个,所以改变任意的一个变量,另外变量也会被影响 var arr = [1,5,6,3] var newArr = arr; newArr.reverse() console.log(arr) // [3,6,5,1] console.log(newArr) // [3,6,5,1] 因为数组也是Object引用类型,所以也要遵循引用类型的规则 ``` ###### Math内置对象 ```javascript // 返回绝对值 console.log(Math.abs(-3)) // 向上取整 console.log(Math.ceil(3.00000000001)) // 向下取整 console.log(Math.floor(3.999999999)) // 四舍五入 console.log(Math.round(3.4)) max(x,y) min(x,y) // 返回 x 的 y 次幂。 pow(x,y) ``` ###### Date对象 ``` javascript // 实例化一个Date对象:返回的时间点是此时此刻,并且不随着时间的移动和自动更新。 var a = new Date() // 返回年份 a.getFullYear() // 返回月份:从0开始 a.getMonth() + 1 // 返回日 a.getDate() // 返回星期几:星期天会返回0 a.getDay() // 时分秒 a.getHours() a.getMinutes() a.getSeconds() ``` ###### 计算两个日期相隔的时间 ```javascript function getTime(){ // 目标时间 var targetDate = new Date("2021-03-03 00:00:00") // 当前时间 var nowDate = new Date() // 返回时间戳 1970-01-01 00:00:00 var total = Math.floor((targetDate.getTime() - nowDate.getTime()) / 1000); var hours = Math.floor(total / 3600) var minutes = Math.floor((total - hours * 3600) / 60) var seconds = total % 60 var hours = hours < 10 ? "0" + hours : hours; var minutes = minutes < 10 ? "0" + minutes : minutes; var seconds = seconds < 10 ? "0" + seconds : seconds; time.innerHTML = hours + ":" + minutes + ":" + seconds; } ``` ###### DOM:document内置对象 * getElementById(id名) 根据id寻找元素,并返回Node节点 * getElementsByTagName(标签名) 根据标签获取元素,并返回NodeList节点列表 * getElementsByClassName() 根据类名获取元素,返回NodeList * querySelectorAll() 根据css选择器返回元素,返回NodeList * querySelector() 根据css选择器返回元素,返回Node * createElement("标签") 创造并返回一个页面中不存在的Node节点 ###### Node节点 * className 设置或返回元素的class属性的属性值 * innerHTML 设置或返回元素的开始标签与结束标签之间的内容 * value 设置或返回文本框与文本域的内容 * setAttribute(key,value) 设置元素的自定义属性 * getAttribute(key) 获取元素的自定义属性的属性值 * getElementsByTagName() * getElementsByClassName() * nextElementSibling 返回下一个紧邻的兄弟节点 * previousElementSibling 返回上一个紧邻的兄弟节点 * parentNode 返回父级节点 * children 找子级元素 * firstElementChild 返回第一个元素子节点 * lastElementChild 返回最后一个元素子节点 * nodeType 节点类型:1元素节点,3文本节点,8注释节点,9document * nodeName 返回该元素节点的标签名(大写字符串) * remove() 删除元素 * appendChild() 插入到结束标签之前 * insertBefore(插入的元素,参照物) * cloneNode(true) 复制一个元素的副本 * style 设置/获取一个元素的行内样式 ###### NodeList节点列表:类数组,它是若干个Node节点组成的一个类数组。一般来说拿到NodeList之后会进行循环。 ###### 计时器 ```javascript // function fn(){ // console.log(1) // } // 只执行一次 // setTimeout(function(){ // fn() // },3000) // setTimeout(fn,3000) // document.getElementById("start").onclick = function(){ // time = setTimeout(function(){ // console.log("计时完毕") // },3000) // } // document.getElementById("stop").onclick = function(){ // clearTimeout(time) // } // setInterval(function,时间) 每个时间参数的毫秒数就调用一次参数1的函数 document.getElementById("start").onclick = function(){ time = setInterval(function(){ console.log("计时完毕") },1000) } document.getElementById("stop").onclick = function(){ clearInterval(time) } ``` ###### 帮助用户触发某个元素的事件:` Node.去on的事件名() ` ###### 鼠标移上和离开事件 ```javascript // 当用户鼠标移动到该元素上时触发的事件 Node.onmouseenter = function(){ } // 当用户鼠标离开该元素时触发的事件 Node.onmouseleave = function(){ } // 获得焦点 Node.onfocus = function(){} // 失去焦点 Node.onblur = function(){} ``` ###### BOM:window内置对象。 ###### 事件 ```javascript node.事件名 = function(event){ // 事件处理函数,事件句柄 // 事件对象:当触发事件时浏览器传入的实参,包含了所有触发事件时浏览器提供的信息。 event } ``` * onclick * onmouseenter * onmouseleave * onfocus * onblur * onmouseover * onmouseout * onmousedown * onmouseup * onmousemove * onkeydown * onkeyup * onkeypress 忽略掉功能键版的onkeydown ###### 鼠标事件对象下的属性: * clientX,clientY:相对于浏览器左上顶点的距离。 * offsetX,offsetY:相对于绑定事件的左上顶点。 * screenX,screenY:相对于屏幕的左上顶点。 * which:检测触发事件的键码,1左键3右键2中键。 ###### 键盘事件对象下的属性: keyCode 返回键码(13是回车) ###### 获取页面的宽度:document.body.clientWidth ###### 获取页面的高度:document.body.clientHeight ###### !!事件传播机制 * 捕获阶段:事件传播机制的第一阶段,从外到内依次寻找元素。 * 冒泡阶段:事件传播机制的第二阶段,从内到外依次寻找元素。 ###### 事件监听 ```javascript // 与普通绑定事件的不同点: // 1.改变事件的触发时机 // 2.可以重复绑定事件处理函数是在累加而非覆盖 // 绑定事件,并在捕获阶段触发事件 Node.addEventListener("去on的事件名",function(){ },true) ``` ###### !!!!!!事件委托:将子级元素的事件委托给它们的父级元素来绑定,然后利用事件对象中的target属性来代替this。 ###### 事件委托所解决的好处 1) 在极端情况下可能节省客户端性能. 2) 解决动态元素无法绑定事件的问题。 ###### 阻止事件继续传播: event.stopPropagation() ###### 阻止浏览器默认行为 * 事件处理函数里return false * event.preventDefault() ###### 正则表达式:描述一种字符串组成规则的对象;笔记地址:https://note.youdao.com/ynoteshare1/index.html?id=63c601e21390ee0d213fd1715e1c40c1&type=note ###### !!!!!!!this指向问题 * 1.this出现在事件处理函数:指向触发事件元素本身。 * 2.this出现在全局作用域或出现在一般函数中:指向window对象。 * 3.this出现在对象的方法中:指向该对象。 * 4.this如果出现在构造函数中:指向该构造函数的实例化对象。 ###### !!!!!箭头函数的this指向问题:箭头函数会改变函数体内部的this指向即每一个函数都会形成一个针对于this的封闭作用域,如果这是一个箭头函数则不会形成封闭作用域,这个箭头函数中的this指向会穿透本层到达上一层作用域上,以上一层this的指向作为本层this的指向。 ###### ES5和ES6新语法:https://note.youdao.com/ynoteshare1/index.html?id=b6bce72d50966daff6395256a822a958&type=note ###### 构造函数:生产对象的工具。 ```javascript // 工厂函数 function person(name,age,sex){ let o = {}; o.name = name; o.age = age; o.sex = sex; o.sayName = function(){ alert(o.name) } return o; } console.log(person("王大伟",18,1)) // 构造函数 function Person(name,age,sex){ this.name = name; this.age = age; this.sex = sex; this.sayName = function(){ alert(this.name) } } // 实例化对象 let wdw = new Person("王大伟",19,1) let fq = new Person("冯倩",18,0) let wh = new Person("伍欢",17,0) let cjj = new Person("程静静",27,0) console.log(wdw) console.log(wdw.type) // -> 返回 "灵长类" console.log(wdw.constructor) // 实例化对象.constructor 返回构造函数的引用 console.log(wdw.__proto__) console.log(wdw.constructor.prototype) ``` ###### 为全局对象扩展原型方法: ```javascript Array.prototype.has = function(query){ let isHas = false; // 指向 实例对象 : 数组 this.forEach(item=>{ if(item === query){ isHas = true; } }) return isHas; } ``` ###### 为所有元素扩展全局方法 ```javascript // 相当于为所有元素节点扩展方法 HTMLElement.prototype.fadeOut = function(speed=0.05,callback){ if(speed === "slow"){speed = 0.02}; if(speed === "fast"){speed = 0.08}; if(typeof speed === "function"){ callback = speed; speed = 0.05; } this.style.opacity = 1; let fadeOut = setInterval(()=>{ let o = parseFloat(this.style.opacity); if(o <= 0){ this.style.opacity = 0; this.style.display = "none"; clearInterval(fadeOut) callback && typeof callback === "function" ? callback() : "" return; } this.style.opacity = o - speed; },16) } ``` ###### js继承的原理:继承就是子类继承父类的静态属性和原型方法;在子类构造函数中,使用call或apply方法调用父类构造函数并改变其this指向就可以继承父类的静态属性;将父类的实例化对象赋值给子类的原型对象就可以利用原型链的机制继承父类的原型属性和原型方法; ###### call和apply有什么区别:call和apply的功能是完全一致的,都是可以执行函数并改变本次函数体内部this指向;参数的个数不同,call从第二个参数开始依次代表函数的实参,而apply的参数固定有两个,第二个是一个数组,代表传入实参的集合。