第15天
Object面向对象-继承
- 概述
- 是什么:父对象的成员(属性和方法),子对象可以直接使用
- 为什么:实现代码重用,节约内存空间,提升网站性能
- 如何:多个子对象共用的属性和方法,都要集中定义在父对象上
- 父对象/原型对象
- 是什么:保护一类子对象共有属性和共有方法
- 如何找到:
子对象.__proto__或构造函数名.prototype - 如何设置共有:
原型对象.属性名=属性值;和原型对象.方法名=function(){}
- 两链一包(面试题)
- 作用域链:查找变量
- 闭包:保护可反复使用的局部变量的词法结构
- 原型链:查找属性和方法;每个对象都有一个属性,即__proto__,指向该对象的原型/父亲,一层一层向上查找就会形成一条链式结构,最终指向Object的原型对象
笔试题
- 如何判断自有和共有
- 判断自有:
obj.hasOwnProperty("属性名")若结果为true,则一定是自有;为false,则可能共有可能没有 - 判断共有:
if(obj.hasOwnProperty("属性名")==false&&"属性名" in obj){共有}else{没有}in会自动在整条原型链上查找,找到则为true,没找到则为false - 完整版公式:
- 判断自有:
if(obj.hasOwnProperty("属性名")){
console.log("自有");
}else{
if("属性名" in obj){
console.log("共有");
}else{
console.log("没有");
}
}
- 如何修改/删除自有和共有
- 自有的修改:
obj.属性名=新值;// 删除:delete obj.属性名; - 共有的修改:
obj.__proto__.属性名=新值;// 删除:delete obj.__proto__.属性名;
- 自有的修改:
- 如何为老IE的数组添加indexOf方法
if(Array.prototype.indexOf===undefined){
Array.prototype.indexOf(key,starti){
starti===undefined&&(starti=0);
for(var i=starti;i<this.length;i++){
if(key==this[i]){
return i;
}
}
return -1;
}
}
- 判断x是不是数组
- 判断x是不是继承自Array.prototype:
Array.prototype.isPrototypeOf(x) - 判断x是不是由Array这个构造函数创建的:
x instanceof Array - 只有数组可用,由ES5提供:
Array.isArray(x) - 输出对象的字符串形式:
Object.prototype.toString.apply(x),若=="[object Array]"则为数组
- 判断x是不是继承自Array.prototype:
- 实现自定义继承
- 两个对象之间设置继承:
子对象.__proto__=父对象; - 多个对象之间设置继承:
构造函数名.prototype=父对象;注意时机,需在创建对象之前设置好继承关系
- 两个对象之间设置继承:
Object面向对象-多态
子对象觉得父对象继承来的成员不好用,在本地定义了同名的自有成员,优先使用自有,屏蔽了父对象的共有成员
第16天
ES5-保护对象
- 四大特性(每个属性都有)
{
value:实际存储属性值;
writable:true(默认)/false; 控制是否可修改
enumerable:true(默认)/false; 控制是否可被for in遍历到
configurable:true(默认)/false; 控制是否可删除
}
如何设置:Object.defineProperties(对象名,{"属性名":{四大特性},...})
- 三个级别
- 防扩展(禁止添加新属性):
Object.preventExtensions(obj); - 密封(禁止添加新属性和删除现有属性):
Object.seal(obj); - 冻结(禁止添加、删除以及修改属性的值):
Object.freeze(obj);
- 防扩展(禁止添加新属性):
ES5-新增的数组API(3组6个,简化for循环)
- 判断
- every():全部满足则返回true,有一个不满足则返回false且不管后续,类似于&&
- some():有一个满足则返回true且不管后续,全都不满足则返回false,类似于||
- 公式:
var bool=arr.every/some(function(val,i,arr){return 判断条件;}) - val即value,指当前元素的值(必须);i指当前元素的下标(可选);arr指数组本身(可选)
- 遍历
- forEach():遍历数组,直接修改原数组
- 公式:
arr.forEach(function(val,i,arr){操作;}) - map():遍历数组,不修改原数组,会返回一个新数组
- 公式:
var newArr=arr.map(function(val,i,arr){return 操作;})
- 过滤和汇总
- 过滤:不修改原数组,会返回符合条件元素组成的新数组
- 公式:
var subArr=arr.filter(function(val,i,arr){return 判断条件;}) - 汇总:即累加
- 公式:
var sum=arr.reduce(function(prev,val,i,arr){return prev+val;},init)
call/apply/bind
- call/apply:临时替换了函数中的this-借用;需直接调用、立即执行
- call单独传入实参,即
函数名.call(借用的对象,实参1,实参2,...); - apply传入一个数组,会将其打散,即函数名.apply(借用的对象,[实参1,实参2,...]);
- call单独传入实参,即
- bind:永久替换了函数中的this-买;可在之后任意时间调用
- 语法:
var 新函数名=原函数名.bind(指定对象,永久实参,...); - 3件事:返回一个原函数的深拷贝;新函数中的this永久绑定为指定对象,不能被call/apply借走;新函数中的参数可永久固定
- 语法:
- 固定套路
- 利用apply打散数组:
var max/min=Math.max/min.apply(Math,arr); - 判断引用类型:
Object.prototype.toString.call/apply(arr); - 将类数组转为普通数组:
var 新数组=Array.prototype.slice.call/apply(类数组);
- 利用apply打散数组:
ES5-其他
- 根据父对象创建子对象,会直接继承其属性和方法;公式:
var 子对象=Object.create(父对象,{"自有属性名":{四大特性},...}) - 严格模式(面试题)
- 开启:在任何作用域的顶部添加"use strict"指令
- 功能:禁止给未声明的变量赋值-解决全局污染;将静默失败升级为报错
ES6
- 模板字符串:如`我的名字叫${name}`
- 使用反引号``来代替普通字符串中的单双引号
- 可在字符串中放入变量,但要加上${...},也就不需要再做字符串的拼接
- 实现了一个简单的js环境
- let关键字
- 用来声明/创建变量,使用let取代var是趋势
- 语法:
let 变量名=值; - 作用:解决了声明提前的问题;添加了块级作用域,一个{}就是一个块,变量只可在块中使用;记录着当前触发事件元素的下标
- 箭头函数:简化回调函数 公式:去掉function,在()和{}之间添加=>;若只有一个形参,可省略();若函数体只有一句话,可省略{};若函数体只有一句话还是return,{}和return都要省略
- for...of循环
- 语法:for(var v of arr){v即value,指当前值}
- 缺点:不能修改原数组,只能返回新数组;不能遍历hash数组/对象,只能遍历索引数组
第17天
DOM
- 概述
- 全称Document Object Model,即文档对象模型,操作html文档
- 每个元素/标签、文本、属性、注释都被视为一个DOM节点/元素/对象
- 面试题:HTML、XHTML、DHTML、XML分别是什么?
- HTML:超文本标记语言,即网页
- XHTML:可扩展超文本标记语言,即更严格的网页
- DHTML:动态HTML,不是一门新语言,而是动态网页技术的统称(HTML+CSS+JS),使离线网页也具有动态效果
- XML:数据格式,正在被JSON替代,可自定义标签
- 为方便各类开发者,DOM被分为3个部分
- 核心DOM:可操作一切结构化文档(包括HTML和XML),虽万能但API繁琐;如elem.setAttribute("属性名,"新属性值");
- HTML DOM:只能操作HTML,虽简化了常用API,但不能操作自定义属性;如elem.属性名="新属性值";
- XML DOM:只能操作XML
- DOM树的树根是document对象,一个页面只有一个document,由浏览器的js解释器自动创建;用来查找元素
- 每个DOM节点都有三大属性
- elem.nodeType:返回节点类型的常数值;若是document节点,则返回9;element节点返回1;attribute节点返回2;text节点返回3
- elem.nodeValue:获取属性节点的值
- elem.nodeName:根据节点的类型返回其名称;若是元素节点则返回标签名,且【全大写】
递归
- 是什么:函数中反复调用自己
- 何时使用:遍历DOM树,层级不明确时使用
- 使用步骤:function 函数名(root){函数体;}
- 函数体中,第一层要做什么操作就直接做
- 判断当前的root有没有下一级,若有则再次调用函数,但传入的实参是下一级
- 算法:深度优先!即优先遍历当前节点的子节点,子节点遍历完才回到兄弟节点
- 缺点:同时开启大量的函数调用,会消耗内存;只有一个情况使用:遍历层级不明确的DOM树以及数据
遍历层级不明确的API:TreeWalker对象
- 使用步骤
- 创建tw:
var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ELEMENT); - 反复调用tw的nextNode方法找到每一个元素,最后没找到则返回null,公式:
while((node=tw.nextNode())!=null){针对node的操作;}
- 创建tw:
- 缺点
- 只能遍历层级不明确的DOM树,不能遍历层级不明确的数据(如json)
- 会自动跳过根
查找元素的补充
- 通过HTML的特点查找
- 通过name查找:
var elems=document.getElementsByName("name的属性值");同标签名和class名,找到是一个集合,没找到是空集合[]
- 通过name查找:
- 通过CSS选择器查找
var elem=document.querySelector("任意css选择器");若匹配到多个,只会返回第一个;若没找到返回nullvar elems=document.querySelectorAll("任意css选择器");返回集合,更适合复杂查找
- 面试题:getXXX和queryXXX的区别?
- 返回结果不同
- getXXX返回的是HTMLCollection,一个动态集合;每次修改DOM树,都会再次查找元素,保证数据和页面对应,效率较低
- queryXXX返回的是NodeList,一个静态集合;只管第一次找到的结果,后续DOM树的修改不会使数据变化,效率较高,支持forEach
第18天
DOM-操作元素的补充
- 内容
- elem.innerHTML:没有兼容性问题
- elem.textContent:虽作为标准方法但有兼容性问题,而innerText对老IE的兼容性较好
- input.value:value值其实就是用户输入的内容
- html属性(左为核心DOM,右为HTML DOM)
- 删除属性值:
elem.removeAttribute("属性名");// elem.属性名=""; - 判断是否有某个属性:elem.hasAttribute("属性名") // elem.属性名!="";
- HTML DOM的缺陷:class必须写成className;不能操作自定义属性;删不干净,属性节点还在,有的属性仍有功能,如href无属性值默认刷新
- 删除属性值:
- css样式
- 只能获取到内联样式,也更推荐操作内联样式
- 如何操作内部/外部样式表?
- 获取想要操作的某个样式表 var sheet=document.styleSheets[i];
- 获取该样式表的所有样式规则 var rules=sheet.cssRules;
- 选出想要操作的某个规则 var rule=rules[i];
- 操作 rule.style.css属性名="css属性值";
DOM-创建元素&渲染页面
- 创建空标签:
var elem=document.createElement("标签名"); - 设置必要的属性或事件
- elem.innerHTML="内容";
- elem.属性名="属性值";
- elem.on事件名=function(){}
- 渲染页面、上DOM树:3种
父元素.appendChild(新元素);追加到末尾父元素.insertBefore(新元素,已有子元素);插入到某个已有子元素之前,导致其他元素的下标改变父元素.replaceChild(新元素,已有子元素);替换掉某个已有子元素
- 删除元素:elem.remove();
- 一句话总结DOM是干什么的:增删改查(元素、文本、属性、样式)
HTML DOM-常用对象
- image对象:只简化了创建
- 语法:
var img=new Image(); - 注意:不是人人都有构造函数创建方式
- 语法:
- form对象:只简化了查找
- 查找form元素:
var form=document.forms[i]; - 查找表单控件:
var inp=form.elements[i];
- 查找form元素:
- select对象
- 属性1:select.options用来获取select的所有option,等效于select.children
- 属性2:select.selectedIndex用来获取当前选中项的下标,做联动必然会用到
- 方法1:
select.add(option);等效于appendChild - 方法2:
select.remove(i);删除下标为i的option - 专属事件:
select.onchange=function(){}选中项发生变化时触发
- option对象:只简化了创建,即
var opt=new Option("innerHTML","value"); select.add(new Option("内容","值"));一句话完成4个操作:创建了空option,设置上了innerHTML和value,上树
第19天
用户确认框
- 语法:
var bool=confirm("提示文字"); - 用户点击确定则返回true,点击取消则返回false