二阶段week4-JavaScript

92 阅读11分钟

day016

1.*****Object面向对象:

1.*****继承:父对象的成员(属性和方法),子对象可以直接使用
	为什么要继承:代码重用,节约内存空间
	何时继承:只要多个子对象公用的属性和方法,都要集中定义在父对象中
2.JS的面向对象是基于原型的
	什么是原型:保存一类子对象共有属性和共有【方法】的父对象(原型对象),每个对象天生就有一个原型
	1.*获取原型对象:21.对象名.__prototype__;前提:必须先创建出一个对象,才可以使用此属性找到原型对象
		2.构造函数名.prototype;-构造函数名:Array,Function,RegExp,Date...(哪怕没有创建过任何对象,也能找到原型)
	2.*****两链一包:
		作用域链:以函数EC的scope chain 属性为起点,经过AO逐级引用,形成的一条链式结构,
		作用:查找变量的,带来了变量的使用规则,优先使用自己的,自己没有找全局,全局没有则报错
		闭包:保护了一个可以反复使用的局部变量的词法结构
		原型链:每个对象都有一个.__prototype__的属性,可以不断的连续.找到爸爸-爷爷-祖祖辈辈,形成的一条链式结构
			经过尝试,发现最顶层:Object.prototype是对象的原型,所以也就有了一句话:万物皆对象
			作用:查找属性和方法,自己没有的属性和方法,可以自动顺着原型链进行查找,所以我们知道为什么人人都可以使用toString,因为toString在最顶层的
	3.获取到原型对象,则可以设置共有属性和共有方法
		原型对象.属性名=属性值//共有属性
		原型对象.方法名=function(){}//共有方法
	自有和共有:
		自有:保存在对象本地的属性
		共有:保存在父(原型)对象的属性,所有的子对象都可以使用
	笔试题:
		1.*如何判断自有和共有:
			判断自有:obj.hasOwnProperty("属性名")
				返回一个boolean值:true说明是自有,false可能是共有,也可能是没有
			判断共有:2个条件
				1.不是自有:obj.hasOwnProperty("属性名")==false;
				2.自动在原型链检查:"属性名" in 对象名;
				if(obj.hasOwnProperty("属性名")==false&&"属性名" in 对象名){//共有}
			完整版:
				if(obj.hasOwnProperty("属性名")){
				console.log("自有")
				}else{
				if("属性名" in "对象名"){
				console.log("共有")
				}else{
				console.log("没有")
				}
				}
		2.*修改或删除属性
			1.修改和删除自有属性
				修改:obj.属性名=新值;
				删除:delete obj.属性名;
			2.修改和删除共有属性
				修改:原型对象.属性名=新值;
				删除:delete 原型对象.属性名;
3.*****为老IE的数组添加indexOf方法 --这道题不是固定的:为某一类人设置一个方法
	if(Array.prototype.indexOf==undefined){//不希望主流浏览器也执行到这些代码,我只希望老IE执行到
		Array.prototype.indexOf=function(key,starti){//indexOf的执行原理
			starti==undefined&&(starti=0)//说明用户没有传入开始位置,我们就给用户设置为从下标0开始查找
			for(var i=starti;i<this.length;i++){
			if(this[i]==key){
				return i;//匹配到了返回对应的下标
			}
			}
			没匹配到返回-1
			return -1
		}

	}
4.*****判断x是不是数组?4种方法
	1.判断x是不是继承自Arrary.prototype
		Arrary.prototype.isPrototypeOf(x)
		如果返回true,说明是数组,否则不是数组
	2.判断x是否由构造函数Array创建的
		x.instanceof Array
	3.ES5提供了一个APIArray.isArray(x);
		此方法不是人人都有的,而且ES5以上的东西,老IE都不知道
	4.***输出对象的字符串形式:
		在Object的prototype原型上放着最原始的toString
		原始的toString,默认输出[object 构造函数名]
		***多态(override)/重写:子对象觉得父对象的成员不好用,可以在本地定义同名成员,覆盖对象之中的成员
			不同的理解:同一个函数,不同的人来使用,效果是不同的,其实根本不是同一个函数
		我希望借用到函数:跳过爸爸,直接去找爷爷拿toString
			Object.prototype.toString.apply(x)=="[object Array]";
	5.实现自定义继承:
		1.实现两个对象之间的继承
			子对象.__proto__=父对象
		2.直接匹配设置继承
			构造函数名.prototype=父对象
			时机:先设置好父对象,再创建子对象

day017

ES5&ES6:就是在ES3的基础上添加了一些新特性、新语法、新API-简化ES3

1.ES5:提供了新特性,新API

1.保护对象:保护对象的属性和方法
	1.四大特征,每个属性都有4大特征
			{
			"value":xxx,//实际保存属性值的地方
			"writable":true,//开关:控制着是否可以被修改
			"enumerable":true,//开关:控制着是否可以被for in 循环遍历到
			"configurable":true;//开关:控制着是否可以被删除,总开关,一旦设置为false,不可逆,也不可以再修改其他特性
			}
	修改四大特征:
	Object.defineProperties(obj,{
		"属性名":{四大特征}
	})
	例:   Object.defineProperties(cat, {
        "gender": { writable: false, enumerable: false, configurable: false },
    })
    2.三个级别:
    	1.防拓展:禁止给对象添加任何新属性
    		Object.preventExtensions(obj);
    	2.密封:禁止给对象添加任何新属性,也不能删除属性
    		Object.seal(bj);
    	3.冻结:禁止给对象添加任何新属性,也不能删除属性,也不能修改属性
    		Object.freeze(obj);

2.*****数组的新的API:3组6个

1.判断:判断数组中的元素是否符合要求
	every - 每一个:判断数组中的每个元素【都】要符合要求,最后结果才为true,类似于&&,只要有一个不满足,结果则为false
		语法:var bool=arr.every(function(val,i,arr){
		console.log(val);//当前元素
		console.log(i);//当前元素的下标
		console.log(arr);//数组本身
		return 判断条件
		})
	some - 有一些:判断数组中的是否【包含】符合要求的元素,只要有一个最后结果则为true,类似||,只要有一个满足,则为true,只有全部都不满足,结果才为false
		语法:var bool=arr.some(val,i,arr){
		return 判断条件
		}
2.遍历:对每个元素执行相同/相似的操作
	forEach:直接修改原数组
		语法:arr.forEach(function(val,i,arr){
		操作
		})
	map:不能修改原数组,返回新数组
		语法:var newArr=arr.map(function(val,i,arr){
		return 操作;
		})
3.过滤和汇总:
	过滤:筛选出原数组中符合条件的元素组成一个新数组,原数组不变
		语法:var newArr=arr.filter(function(val,i,arr){
		return 判断条件;
		})
	汇总:将数组中每一个元素,取出来整合为一个最总结果
		语法:var sum=arr.reduce(function(val,i,arr){
			return prev+val;
		},基础值)
以上6API其实都是简化了for循环,此6API只有数组可以使用

3.Object.create()方法:直接用父对象创建子对象,并且子对象扩展自有属性

语法:var 子对象=Object.create(父对象,{
	"自有属性名":{四大特性},
	....
})

4.严格模式:很严格

如何开启:"use strict",可以放在任何一个作用域的顶部
1.禁止给未声明的变量赋值 -解决了全局污染
2.将静默失败升级为了错误
以后如果三阶段学了gulp和webpack,可能打包时就会自动给你生成一个"use strict",你去把他删掉

5.*****call,apply,bind:不是自己的方法,也可以用到

1.call,apply:【临时替换数组中的this】,借用
	差别:call,要求传入函数的实参必须单独参入
		apply,要求传入的实参必须是一个数组
	语法:要借用的函数.call(借用的对象,实参1,...)
		要借用的函数.apply(借用的对象,arr);--apply除了有借用的功能还会悄悄的打散数组
2.bind:【永久替换函数中的this】,买
	语法:var 新函数=老函数.bind(指定的对象)
	3件事:
		1.创建了一个和原函数功能完全一样的函数
		2.将函数中的this永久绑定为指定的对象
		3.将新函数中的部分参数永久固定
	强调:bind绑定在新函数中的this,无法被call,apply再次替换接走
总结:如果临时用一个函数,立刻执行 --call/apply
	如果创建一个函数提前绑定this,不一定希望立即执行 --bind
使用场景:
	1.比较出数组中的最大值和最小值:Math.max/min.apply(Math,arr)
	2.得到Object最原始的toString:Object.prototype.toString.call/apply(数组对象)
	3.将类数组对象转为普通数组:var 新数组=Array.prototype.slice.call/apply(数组对象)
		ES5提供了一个数组API,可以直接将类数组对象转为普通数组:var 新数组=Array.form(类数组对象)

ES6新语法:

0:常量
1.*模版字符串:简化字符串拼接,支持在模版字符串中书写变量
	语法:`我的名字叫${name}`
		在字符串中实现了一个简单的js环境
2.*let关键字:创建变量优先考虑使用let,再用var 
	let 变量名=值
	优点:
		1.解决了声明提前-更符合现实,先创建,再使用
		2.添加了块级作用域,一个{}就是一个块
		3.如果绑定事件时,用到了let遍历,那么let就会记录住你当前元素的下标-以后可以不用自定义下标
3.*箭头函数:简化一切的回调函数
	去掉function,()和{}之间添加=>,行参只有一个可以省略()
	函数体只有一句话,省略{}
	函数体只有一句话,而且是return,省略{}和return
4.for...of:
	for(var v of arr){
		v //直接拿到值
	}
	1.不能修改原数组
	2.不能遍历hash数组和对象
5.解构赋值
6.SetMap类型
7.模块化开发
8.Promise
9.Class

day018

1.什么是DOM:Document Object Model(文档对象模型)

面试题:HTML/XHTML/DHTML/XML分别是什么
	1.HTML:网页
	2.XHTNL:更严格的HTML HTML5->XHTML->HTML4.0
	3.DHTML:动态的网页:DDynamic-在离线时,页面也具有动态效果(Dhtml:html+css+js(dom))
	4.XML:未知的标记语言,一切的标记由自己定义,数据格式
DOM:原本是可以操作一切结构化文档的HTMLXML,后来为了方便各类开发者,分为了3部分
	1.*核心DOM:【无敌】,既可以操作HTML,又可以操作XML。 缺陷:API比较繁琐
	2.*HTML DOM:只能操作HTMLAPI简单,缺陷:比如属性部分,只能访问标准属性,不能访问自定义属性
	3.XML DOM:只能操作XMLXML已经淘汰了,现在流行的数据格式是JSON
	开发建议:优先HTML DOMHTML DOM实现不了的我们再使用核心DOM进行补充

2.DOM树:

        树根:document - 不需要我们创建,一个页面只有一个document对象,由浏览器的js解释器自动创建
	作用:可以通过树根找到页面上的每一个DOM元素/节点/对象,也可以操作它

3.每个DOM元素都有三大属性:

1.element.nodeType:描述节点的类型
	document节点:9
	element节点:1
	attribute节点:2
	text节点:3
	以前有用:判断xx是不是一个页面元素 - 因为children是不会得到文本节点的,但是childNodes会得到文本节点
2.attribute.nodeValue:描述节点的值
	先拿到节点属性,再用此属性去获取属性值
3.***elem.nodeName:描述节点的名字
	拿到当前元素的标签名,判断xx是什么标签
	注意:返回的是一个全大写组成的标签名

4.*通过 关系 获取元素

父:xx.parentNode
子:xx.children - 集合:只能找到儿子
第一个儿子:xx.firstElementChild
最后一个儿子:xx.lastElementChild
前一个兄弟:xx.previousElementSibling
后一个兄弟:xx.nextElementSibling

5.*****递归:

简单来说就是函数中,又一次调用了函数自己,迟早有一天会停下来
何时使用:遍历DOM树,专门用于【遍历层级不明确】的情况,既可以遍历层级不明确的DOM树,也可以遍历层级不明确的数据
如何使用:2function 函数名(root){
		1.第一层要做什么直接做!
		2.判断他有没有下一级,如果有下一级,再次调用此函数,但是传入的实参是他的下一级元素
	}
	函数名(实际的根)
算法:深度优先!优先遍历当前元素的子节点,子节点遍历完才会跳到兄弟节点
递归的缺点:同时开启大量的函数调用,大量消耗内存,只有一个情况才用:【遍历层级不明确】
递归vs循环
递归:优点:直观,易用
	缺点:性能较低,尽量只在层级不明确的时候使用
循环:优点:几乎不占用内存
	缺点:难

6.专门提供了一个遍历层级不明确的DOM树的API:TreeWalker -这是一个在DOM树上行走的人

2步:
1.先创建出tw:
	var tw=document.creatTreeWalker(根元素,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
2.tw对象过后,你会得到一个方法,反复调用nextNode方法找到下一个节点,迟早有一天会等于null,说明没找到,公式
	while((node=tw.nextNode())!=null){
	node要干什么
	}
	缺点:1.自动的跳过根元素,根元素是不会做任何操作的
		 2.仅仅只能遍历层级不明确的DOM树,不能遍历层级不明确的数据

7.API直接找到元素

1.根据HTML的特点去找元素
	IDvar elem=document.getElementById("id值")
	*标签名和*classname:var elems=document.getElementsByTagName/ClassName/Name("标签名/class名")
2.***根据css选择器去找元素
	1.单个元素:
		var elem=document.querySelector("任意的css选择器")
		强调:万一选择器匹配到多个,只会返回第一个,没找到返回null
	2.***多个元素
		var elems=document.querySelectorAll("任意的css选择器")
		强调:找到了返回集合,没找到返回空集合
		更适合做复杂查找

面试题/笔试题: getXXX和querySelectorAll有什么区别? 返回结果的不同: 1.getXXX:返回的是一个动态集合HTMLCollection 优点:数据始终和DOM树实时挂钩 缺点:每次DOM树进行修改,都会悄悄的再次的找到元素,效率相对较低 2.querySelectorAll:返回的是一个静态集合NodeList 优点:每次不会悄悄重新查找,效率较高,而且还支持forEach! 总结:现在【找元素】的方式 1.直接查找元素:getXXX/querySelectorAll 2.通过关系找到元素 3.层级不明确的才用递归!

day019

操作元素(上午) <标签 属性名="属性值" style="样式">内容</标签> 强调:页面上获取/设置到的一切数据都是字符串

1.元素的内容:

1.*elem.innerHTML:获取或设置开始标签到结束标签之间的HTML代码,没有兼容性问题的,可以识别标签
	获取:elem.innerHTML
	设置:elem.innerHTML=""
2.elem.textContent:获取或设置开始标签到结束标签之间的纯文本,有兼容性问题,老IE不支持,不可以识别标签
	获取:elem.textContent
	设置:elem.textContent="新内容"
	老IE:elem.innerText;在某次浏览器更新后,也支持此属性
3.*input.value:获取或设置表单控件的值 - 只要做正则验证,就一定需要用到
	获取:input.value
	设置:input.value="新值"

2.元素的属性

1.获取属性值:
	核心DOMelem.getAttribute("属性名")
	HTML DOMelem.属性名;
2.设置属性值:
	核心DOMelem.setAttribute("属性名","属性值");
	HTML DOMelem.属性名="属性值"
3.删除属性值:
	核心DOMelem.removeAttribute("属性名")
	HTML DOM:elem.属性名="" - 删除不推荐使用HTML DOM ,删除不干净属性节点,而有的属性,光有属性名就已经具有该功能了
4.判断有没有属性值:
	核心DOMelem.hasAttribute("属性名")-仅仅只能判断有没有这个属性,不能判断出属性值是什么,往往需要自己获取到属性值,然后进行比较运算
	HTML DOMelem.属性名!=""
HTML DOM的缺陷:
	1.class需要写为className
	2.不能操作自定义属性
开发中:优先使用HTML DOM.HTML DOM 满足不了再用核心DOM补充

3.元素的样式:

1.*内联样式:优先级最高,一定会覆盖其他的样式
	仅仅当前元素可用,不会牵一发动全身
	获取样式:elem.style.css属性名;
	设置样式:elem.style.css属性名="属性值"
	唯一的缺陷:获取样式时,只能获取到内联样式
2.样式表中的样式:
	//1、找到你想要操作的样式表
	var sheet=document.styleSheets[i];
	//2、获取样式表中所有的样式规则
	var rules=sheet.cssRules;
	//3、找到自己想要操作的样式规则
	var rule=rules[i];
	//4、要么获取要么设置
	console.log(rule.style.css属性名);
	rule.style.css属性名="css属性值";
一切的获取都是为了判断
一切的设置都是修改或者添加

下午:

1.创建元素并且渲染DOM树:3步

1.创建空标签:
	var elem=document.creatElement("标签名")
2.添加必要的属性和事件
	elem.属性名="属性值"
	elem.on时间名=function(){操作;}
3.上树:将js内存中的新标签放到DOM树上
	*父元素.appendChild(elem);将elem追加到元素里当最后一个儿子
	父元素.insertBefore(elem,已有子元素)
	将elem追加到父元素里,但是会插入再已有子元素的前面,缺点:会影响到其他元素的下标
	父元素.replaceChild(elem,已有子元素) - 将elem追加到父元素里,但是会替换已有子元素

2.删除元素:elem.remove()

HTML DOM常用对象:【简化核心DOM1.image对象:仅仅只是简化了创建语句
	创建:var img= new Image()  ===var elem=document.createElement("img")
	注意:不是人人都有构造函数的创建方式
2.form对象:简化了查找元素
	查找form元素:var form=document.form[i];
	查找form元素中的表单控件:var inp=form.elements[i]
	*专属事件:form.onsubmit=function(){//提交事件:只会在提交的一瞬间执行
		return false;//阻止提交
	}
3.*select对象:仅仅只是简化了创建语句,但是非常实用
	创建:var opt=new Option("innerHTML","value");
	一句话完成4个操作
		select.add(new Option("innerHTML","value"))

day20 复习:

1.DOM作业:增、删、改、查(元素,内容,属性,样式)

1.元素
	1.增-元素:
		//创建空标签
		var elem=document.createElement("标签名")
		//设置必要的属性和事件
		elem.属性名=属性值
		elem.on事件名=function(){操作}
		//上树
		父元素.appendChild(elem); - 追加到末尾
		父元素.insertBefore(elem,已有子元素);-插入到已有子元素的前面
		父元素.replaceChild(elem,已有子元素); -替换已有子元素
	2.删-元素:elem.remove();
	3.改-元素:父元素.replaceChild(elem,已有子元素);
	4.查-元素:
		1.直接查找:document.getXXX/querySelectAll
		2.通过关系查找:
		3.遍历层级不明确的结构/数据:递归
2.内容
	1.增:elem.innerHTML/innerText/value+="新内容";
	2.删:elem.innerHTML/innerText/value="";
	3.改:elem.innerHTML/innerText/value="新内容";
	4.查:elem.innerHTML/innerText/value;
3.属性:核心DOM												HTMLDOM
	1.增:elem.setAttribute("属性名","旧属性值 新属性值");  == elem.属性名="属性值";
	2.删:elem.removeAttribute("属性名");					==elem.属性名="";
	3.改:elem.setAttribute("属性名","属性值");			==elem.属性名="属性值";
	4.查:elem.getAttribute("属性名");					==elem.属性名;
4.样式:
	1.增:elem.style.css属性名="css属性值"		-没有的话,就是添加
	2.删:elem.style.css属性名=""
	3.改:elem.style.css属性名="css属性值" 	-有的话,就是修改
	4.查:elem.style.css属性名;				-只能查到内联/行内样式

HTML DOM常用对象:

select.add(new Option("内容","值"));
select.selectedIndex; -获取select选中的option下标

笔记:

1.浏览器一共提供了3种弹出框:
1.警告框:alert();
2.用户输入框:var user=prompt("提示文字","默认值");
3.用户确认框:var bool=confirm("提示文字");