JavaScript第四周学习总结

139 阅读7分钟

第15天

Object面向对象-继承

  • 概述
    1. 是什么:父对象的成员(属性和方法),子对象可以直接使用
    2. 为什么:实现代码重用,节约内存空间,提升网站性能
    3. 如何:多个子对象共用的属性和方法,都要集中定义在父对象上
  • 父对象/原型对象
    1. 是什么:保护一类子对象共有属性和共有方法
    2. 如何找到:子对象.__proto__构造函数名.prototype
    3. 如何设置共有:原型对象.属性名=属性值;原型对象.方法名=function(){}
  • 两链一包(面试题)
    1. 作用域链:查找变量
    2. 闭包:保护可反复使用的局部变量的词法结构
    3. 原型链:查找属性和方法;每个对象都有一个属性,即__proto__,指向该对象的原型/父亲,一层一层向上查找就会形成一条链式结构,最终指向Object的原型对象

笔试题

  • 如何判断自有和共有
    1. 判断自有:obj.hasOwnProperty("属性名")若结果为true,则一定是自有;为false,则可能共有可能没有
    2. 判断共有:if(obj.hasOwnProperty("属性名")==false&&"属性名" in obj){共有}else{没有}in会自动在整条原型链上查找,找到则为true,没找到则为false
    3. 完整版公式:
        if(obj.hasOwnProperty("属性名")){
            console.log("自有");
        }else{
            if("属性名" in obj){
                console.log("共有");
            }else{
                console.log("没有");
            }
        }
  • 如何修改/删除自有和共有
    1. 自有的修改:obj.属性名=新值; // 删除:delete obj.属性名;
    2. 共有的修改: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是不是数组
    1. 判断x是不是继承自Array.prototype:Array.prototype.isPrototypeOf(x)
    2. 判断x是不是由Array这个构造函数创建的:x instanceof Array
    3. 只有数组可用,由ES5提供:Array.isArray(x)
    4. 输出对象的字符串形式:Object.prototype.toString.apply(x),若=="[object Array]"则为数组
  • 实现自定义继承
    1. 两个对象之间设置继承:子对象.__proto__=父对象;
    2. 多个对象之间设置继承:构造函数名.prototype=父对象;注意时机,需在创建对象之前设置好继承关系

Object面向对象-多态

子对象觉得父对象继承来的成员不好用,在本地定义了同名的自有成员,优先使用自有,屏蔽了父对象的共有成员

第16天

ES5-保护对象

  • 四大特性(每个属性都有)
{
    value:实际存储属性值;
    writable:true(默认)/false;     控制是否可修改
    enumerable:true(默认)/false;   控制是否可被for in遍历到
    configurable:true(默认)/false; 控制是否可删除
}

如何设置:Object.defineProperties(对象名,{"属性名":{四大特性},...})

  • 三个级别
    1. 防扩展(禁止添加新属性):Object.preventExtensions(obj);
    2. 密封(禁止添加新属性和删除现有属性):Object.seal(obj);
    3. 冻结(禁止添加、删除以及修改属性的值):Object.freeze(obj);

ES5-新增的数组API(3组6个,简化for循环)

  • 判断
    1. every():全部满足则返回true,有一个不满足则返回false且不管后续,类似于&&
    2. some():有一个满足则返回true且不管后续,全都不满足则返回false,类似于||
    3. 公式:var bool=arr.every/some(function(val,i,arr){return 判断条件;})
    4. val即value,指当前元素的值(必须);i指当前元素的下标(可选);arr指数组本身(可选)
  • 遍历
    1. forEach():遍历数组,直接修改原数组
    2. 公式:arr.forEach(function(val,i,arr){操作;})
    3. map():遍历数组,不修改原数组,会返回一个新数组
    4. 公式:var newArr=arr.map(function(val,i,arr){return 操作;})
  • 过滤和汇总
    1. 过滤:不修改原数组,会返回符合条件元素组成的新数组
    2. 公式:var subArr=arr.filter(function(val,i,arr){return 判断条件;})
    3. 汇总:即累加
    4. 公式:var sum=arr.reduce(function(prev,val,i,arr){return prev+val;},init)

call/apply/bind

  • call/apply:临时替换了函数中的this-借用;需直接调用、立即执行
    1. call单独传入实参,即函数名.call(借用的对象,实参1,实参2,...);
    2. apply传入一个数组,会将其打散,即函数名.apply(借用的对象,[实参1,实参2,...]);
  • bind:永久替换了函数中的this-买;可在之后任意时间调用
    1. 语法:var 新函数名=原函数名.bind(指定对象,永久实参,...);
    2. 3件事:返回一个原函数的深拷贝;新函数中的this永久绑定为指定对象,不能被call/apply借走;新函数中的参数可永久固定
  • 固定套路
    1. 利用apply打散数组:var max/min=Math.max/min.apply(Math,arr);
    2. 判断引用类型:Object.prototype.toString.call/apply(arr);
    3. 将类数组转为普通数组:var 新数组=Array.prototype.slice.call/apply(类数组);

ES5-其他

  • 根据父对象创建子对象,会直接继承其属性和方法;公式:var 子对象=Object.create(父对象,{"自有属性名":{四大特性},...})
  • 严格模式(面试题)
    1. 开启:在任何作用域的顶部添加"use strict"指令
    2. 功能:禁止给未声明的变量赋值-解决全局污染;将静默失败升级为报错

ES6

  • 模板字符串:如`我的名字叫${name}`
    1. 使用反引号``来代替普通字符串中的单双引号
    2. 可在字符串中放入变量,但要加上${...},也就不需要再做字符串的拼接
    3. 实现了一个简单的js环境
  • let关键字
    1. 用来声明/创建变量,使用let取代var是趋势
    2. 语法:let 变量名=值;
    3. 作用:解决了声明提前的问题;添加了块级作用域,一个{}就是一个块,变量只可在块中使用;记录着当前触发事件元素的下标
  • 箭头函数:简化回调函数 公式:去掉function,在()和{}之间添加=>;若只有一个形参,可省略();若函数体只有一句话,可省略{};若函数体只有一句话还是return,{}和return都要省略
  • for...of循环
    1. 语法:for(var v of arr){v即value,指当前值}
    2. 缺点:不能修改原数组,只能返回新数组;不能遍历hash数组/对象,只能遍历索引数组

第17天

DOM

  • 概述
    1. 全称Document Object Model,即文档对象模型,操作html文档
    2. 每个元素/标签、文本、属性、注释都被视为一个DOM节点/元素/对象
  • 面试题:HTML、XHTML、DHTML、XML分别是什么?
    1. HTML:超文本标记语言,即网页
    2. XHTML:可扩展超文本标记语言,即更严格的网页
    3. DHTML:动态HTML,不是一门新语言,而是动态网页技术的统称(HTML+CSS+JS),使离线网页也具有动态效果
    4. XML:数据格式,正在被JSON替代,可自定义标签
  • 为方便各类开发者,DOM被分为3个部分
    1. 核心DOM:可操作一切结构化文档(包括HTML和XML),虽万能但API繁琐;如elem.setAttribute("属性名,"新属性值");
    2. HTML DOM:只能操作HTML,虽简化了常用API,但不能操作自定义属性;如elem.属性名="新属性值";
    3. XML DOM:只能操作XML
  • DOM树的树根是document对象,一个页面只有一个document,由浏览器的js解释器自动创建;用来查找元素
  • 每个DOM节点都有三大属性
    1. elem.nodeType:返回节点类型的常数值;若是document节点,则返回9;element节点返回1;attribute节点返回2;text节点返回3
    2. elem.nodeValue:获取属性节点的值
    3. elem.nodeName:根据节点的类型返回其名称;若是元素节点则返回标签名,且【全大写】

递归

  • 是什么:函数中反复调用自己
  • 何时使用:遍历DOM树,层级不明确时使用
  • 使用步骤:function 函数名(root){函数体;}
    1. 函数体中,第一层要做什么操作就直接做
    2. 判断当前的root有没有下一级,若有则再次调用函数,但传入的实参是下一级
  • 算法:深度优先!即优先遍历当前节点的子节点,子节点遍历完才回到兄弟节点
  • 缺点:同时开启大量的函数调用,会消耗内存;只有一个情况使用:遍历层级不明确的DOM树以及数据

遍历层级不明确的API:TreeWalker对象

  • 使用步骤
    1. 创建tw:var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ELEMENT);
    2. 反复调用tw的nextNode方法找到每一个元素,最后没找到则返回null,公式:while((node=tw.nextNode())!=null){针对node的操作;}
  • 缺点
    1. 只能遍历层级不明确的DOM树,不能遍历层级不明确的数据(如json)
    2. 会自动跳过根

查找元素的补充

  • 通过HTML的特点查找
    1. 通过name查找:var elems=document.getElementsByName("name的属性值");同标签名和class名,找到是一个集合,没找到是空集合[]
  • 通过CSS选择器查找
    1. var elem=document.querySelector("任意css选择器");若匹配到多个,只会返回第一个;若没找到返回null
    2. var elems=document.querySelectorAll("任意css选择器");返回集合,更适合复杂查找
  • 面试题:getXXX和queryXXX的区别?
    1. 返回结果不同
    2. getXXX返回的是HTMLCollection,一个动态集合;每次修改DOM树,都会再次查找元素,保证数据和页面对应,效率较低
    3. queryXXX返回的是NodeList,一个静态集合;只管第一次找到的结果,后续DOM树的修改不会使数据变化,效率较高,支持forEach

第18天

DOM-操作元素的补充

  • 内容
    1. elem.innerHTML:没有兼容性问题
    2. elem.textContent:虽作为标准方法但有兼容性问题,而innerText对老IE的兼容性较好
    3. input.value:value值其实就是用户输入的内容
  • html属性(左为核心DOM,右为HTML DOM)
    1. 删除属性值:elem.removeAttribute("属性名"); // elem.属性名="";
    2. 判断是否有某个属性:elem.hasAttribute("属性名") // elem.属性名!="";
    3. HTML DOM的缺陷:class必须写成className;不能操作自定义属性;删不干净,属性节点还在,有的属性仍有功能,如href无属性值默认刷新
  • css样式
  • 只能获取到内联样式,也更推荐操作内联样式
  • 如何操作内部/外部样式表?
    1. 获取想要操作的某个样式表 var sheet=document.styleSheets[i];
    2. 获取该样式表的所有样式规则 var rules=sheet.cssRules;
    3. 选出想要操作的某个规则 var rule=rules[i];
    4. 操作 rule.style.css属性名="css属性值";

DOM-创建元素&渲染页面

  • 创建空标签:var elem=document.createElement("标签名");
  • 设置必要的属性或事件
    1. elem.innerHTML="内容";
    2. elem.属性名="属性值";
    3. elem.on事件名=function(){}
  • 渲染页面、上DOM树:3种
    1. 父元素.appendChild(新元素);追加到末尾
    2. 父元素.insertBefore(新元素,已有子元素);插入到某个已有子元素之前,导致其他元素的下标改变
    3. 父元素.replaceChild(新元素,已有子元素);替换掉某个已有子元素
  • 删除元素:elem.remove();
  • 一句话总结DOM是干什么的:增删改查(元素、文本、属性、样式)

HTML DOM-常用对象

  • image对象:只简化了创建
    1. 语法:var img=new Image();
    2. 注意:不是人人都有构造函数创建方式
  • form对象:只简化了查找
    1. 查找form元素:var form=document.forms[i];
    2. 查找表单控件:var inp=form.elements[i];
  • select对象
    1. 属性1:select.options用来获取select的所有option,等效于select.children
    2. 属性2:select.selectedIndex用来获取当前选中项的下标,做联动必然会用到
    3. 方法1:select.add(option);等效于appendChild
    4. 方法2:select.remove(i);删除下标为i的option
    5. 专属事件:select.onchange=function(){}选中项发生变化时触发
  • option对象:只简化了创建,即var opt=new Option("innerHTML","value");
  • select.add(new Option("内容","值"));一句话完成4个操作:创建了空option,设置上了innerHTML和value,上树

第19天

用户确认框

  • 语法:var bool=confirm("提示文字");
  • 用户点击确定则返回true,点击取消则返回false