-
Object面向对象\
-
继承
父对象的成员(属性和方法),子对象可以直接使用- 为什么
代码重用,节约内存空间
- 何时
只要多个子对象公用的属性和方法都要集中定义在父对象之中
- 为什么
-
JS的面向对象是基于原型(父亲)的\
- 原型:保存一类子对象共有属性和方法的父对象(原型对象),每个对象天生有一个原型\
-
获取原型对象\
- 对象名.proto;
必须先创建出一个对象,才可以使用
- 构造函数名.prototype;
构造函数名:Array、Function、Date、RegExp - 哪怕没有创建对象也能找到原型
- 对象名.proto;
-
两链一包\
-
作用域链\
- 一函数EC的scope chain属性为启迪那,经过AO逐级引用,形成从一条链式结构\
- 作用:查找变量的,带来了变量的使用规则;优先使用自己的,自己没有找到全局对象\
-
闭包\
- 保护了一个可以反复使用的局部变量的词法结构\
-
原型链\
- 每个对象都有一个.__proto__的属性,可以不断的连续找到爸爸-爷爷...形成的一条链式结构\
- 经过尝试,发现最顶层Object.prototype是对象的原型,即“万物皆对象”\
- 作用:查找属性和方法,自己没有的属性和对象,可以自动顺着原型链进行查找\
-
-
获取到原型对象则可以设置共有属性和共有方法
原型对象.属性名=属性值;//共有属性
原型对象.方法名=function; //共有方法\-
自有和共有\
- 自有:保存在对象本地的属性\
- 共有:保存在父(原型)对象的属性,所有的子对象都可以使用\
-
笔试题\
-
1、如何判断自有和共有\
- 判断自有:obj.hasOwnProperty(“属性名”)
返回一个布尔值:true说明是自有,false说明可能是共有也有可能是没有
-
判断共有:2个条件\
- 不是自有:obj.hasOwnProperty(“属性名”)\
- 自动在原型链检查:"属性名"in 对象名
if(obj.hasOwnProperty("属性名")==false&&"属性名"in 对象名){//共有}
完整版:
if(obj.hasOwnProperty("属性名")){
console.log("自有");
}else{
if("属性名" in 对象名){
console.log("共有")
}else{
console.log("没有")
}
}\
- 判断自有:obj.hasOwnProperty(“属性名”)
-
2、修改或删除属性\
-
自有\
- 修改:obj.属性名=新值\
- 删除:delete obj.属性名\
-
共有\
- 修改:原型对象.属性名=新值\
- 删除: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
if(this[i]==key){
return i;//匹配到了返回对应的下标
}
}
//没匹配到,返回-1
return -1;
}
}
-
4、判断x是不是数组(4种方法)\
- a.判断x是不是继承自Array.prototype
Array.prototype.isPrototypeOf(x);
如果返回true,说明是数组,否则不是数组
- b.判断是否是由构造函数Array创建的
x instanceof Array
- ES5提供的API:Array.isArray(x)(老IE不支持)\
-
输出对象的字符串形式
Object的prototype原型上放着最原始的toString,原始的toString,默认输出[object 构造函数名]-
多态(override)/重写
子对象绝对父对象的成员不好用,可以在本地定义同名成员,覆盖父对象之中的成员- Object.prototype.toString.apply(x)==="[object Array]";\
-
- a.判断x是不是继承自Array.prototype
-
实现自定义继承\
-
实现两个对象之间的基础\
- 子对象.proto=父对象;\
-
直接匹配设置继承\
- 构造函数名.prototype=父对象;
先设置好父对象,再创建子对象
- 构造函数名.prototype=父对象;
-
-
-
-
-
ES5
在ES3的基础添加了一些新特性、新语法、新API---简化ES3 -
1、保护对象
保护对象的属性和方法-
1、四大特性
每个属性都有四大特性
{
"value": 3500, //实际保存属性值的地方
"writable": true,//开关:控制着是否可以被修改
"enumerable": true,//开关:控制着是否可以被for in循环遍历到
"configurable": true//开关:控制着是否可以被删除
}\
- 修改四大特性
object.defineProperties(obj,{
"属性名":{四大特性}
})
-
2、三个级别\
-
防扩展
禁止给对象添加任何新属性- object.preventExtensions(obj);\
-
密封
禁止给对象添加任何新属性,也不能删除属性- object.seal(obj);\
-
冻结
禁止给对象添加任何新属性,也不能删除属性,也不能修改属性- object.freeze(obj);\
-
-
-
数组的新API\
-
1、判断\
-
every
每一个:判断数组中的每个元素都要复合要求最后结果才为true,类似&&- 语法
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(function(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(prev,val,i,arr){
return prev+val;
},基础值)
- 语法
-
-
-
Object.create()方法
直接用父对象创建子对象,并且子对象扩展自有属性- 语法
var 子对象=Object.create(父对象,{
"自有属性":{四大特性},
...
}
- 语法
-
严格模式:很严格(最好不用)
用"use strict";开启- 禁止给未声明的对象赋值---解决了全局污染\
- 将静默失败升级为错误\
-
call,aplly,bind\
-
1、call,apply:临时替换函数中的this,借用\
-
差别\
- call要求传入函数的实参必须单独传入\
- apply要求传入函数的实参必须是一个数组\
-
语法\
- 要借用的函数.call(借用的对象,实参1,...);\
- 要借用的函数.apply(借用的对象,arr);\
-
-
2、bind
永久替换函数中的this,买- 语法
var 新函数=老函数.bind(指定的对象)
-
3件事\
- 1、创建了一个和原函数功能完全一样的新函数\
- 2、将新函数中的this永久绑定为你指定的对象\
- 3、将新函数中的步伐参数永久固定\
-
强调\
- bind绑定在新函数中的this,无法被call、apply再次替换节奏\
- 语法
-
总结:\
- 如果临时调用一个函数,立刻执行时---call/apply\
- 如果创建一个饿汉式提前绑定this,不一定希望理科执行---bind\
-
使用场景\
- 比较出数组中的最大值和最小值
Math.max/min.apply(Math,arr);
- 得到Object最原始的toString
Object.prototype.toString.call/apply(arr);
-
将类数组对象转为普通数组
var 新数组=Array.prototype.slice.call/apply(类数组对象);- ES5还提供了一个数组API,可以直接将类数组对象转为普通数组:var 新数组=Array.from(类数组对象)\
- 比较出数组中的最大值和最小值
-
-
ES6新语法\
-
1、模板字符串
在字符串中实现了一个简单的js环境- 语法
我的名字是${name}
- 语法
-
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数组和对象\
- 语法
-
-
1、DOM
document Object Model(文档对象模型)-
面试题\
-
HTML/XHTML/DHTML/XML分别是什么\
- 1、HTML--网页\
- 2、XHTML--更严格的HTML,HTML5--XHTML--HTML4.01\
- 3、DHTML--动态网页,D:Dynamic--将现有计算的整合统称,让我们离线时也具有动态效果
DHTML:html+css+js(dom)
- 4、XML--未知的标记语言,一切标记由自己定义,数据格式\
-
-
DOM为了方便各类开发者,分为了3部分\
-
1、核心DOM\
- 既可以操作HTML,又可以操作XML\
- 缺点:API比较繁琐\
-
2、HTML DOM\
- 只能操作HTML,API简单\
- 缺点:比如属性部分,只能访问标准属性,不能访问自定义属性\
-
3、XML DOM\
- 只能操作XML,但XML已经淘汰了,现在最流行的数据格式是JSON\
- 开发建议:有限HTML DOM,HTML DOM实现不了再用核心DOM进行补充\
-
-
-
2、DOM树\
- 树根:document
不需要我们创建,一个页面只有一个document对象,由浏览器的js解释器自动创建
-
作用\
- 可以通过树根找到页面上的每一个DOM元素/节点/对象,也可以操作它\
- 树根:document
-
3、每个DOM元素都有三大属性\
-
1.elem.nodeType
描述节点的类型,现在不用,直接方法children- document节点:9\
- element节点:1\
- attribute节点:2\
- text节点:3\
-
2.attrNode.nodeValue
描述节点的值- 以前有用,先拿到属性节点,再用属性获取属性值\
-
3.elem.nodeName
描述节点的名字- 拿到当前元素的标签名,判断是什么标签\
- 返回的是一个全大写组成的标签名\
-
-
通过关系过去元素\
- 父:xx.parentNode\
- 子:xx.children------是集合,只能找到儿子\
- 第一个儿子:xx.firstElementChild\
- 最后一个儿子:xx.lastElementChild\
- 前一个兄弟:xx.previousElementSling\
- 后一个兄弟:xx.nextElementSibling\
-
***** 递归
简单来说就是函数中又一次调用量函数自己,迟早有一天会停下来- 何时使用
遍历DOM树,专门用于遍历层级不明确的情况,既可以遍历层级不明确的DOM树,也可以遍历层级不明确的数据
- 如何使用(2步)
function 函数名(root){
1、第一层要做什么直接做
2、判断有没有下一级,如果有,再次调用此函数,但是传入的实参是他的下一级
}
函数名(实际的根)
-
算法\
- 深度优先!优先遍历当前系统的子节点,子节点遍历完才会跳到兄弟节点\
-
缺点\
- 同时开启大量的函数调用,大量消耗内存,只有遍历层级不明确的时候使用\
-
递归和循环对比\
-
递归\
- 优点:直观、易用\
- 缺点:性能较低,尽量只在层级不明确的时候使用\
-
循环\
- 优点:几乎不占用内存\
- 缺点:太难\
-
- 何时使用
-
6、TreeWalker
在DOM树上行走的遍历层级不明确的DOM树的API- 1、创建tw
var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
-
2、tw对象过后,会得到一个方法,反复调用nextNode方法找到下一个节点,迟早有一天会等于null,说明没找到
while((node=tw.nextNode())!=null){
node要干什么
}\-
缺点\
- 自动的跳过根元素,根元素是不会做任何操作的\
- 仅仅只能遍历层级不明确的DOM树,不能遍历层级不明确的数据\
-
- 1、创建tw
-
7、API直接找元素\
-
1、根据HTML的特点找元素\
- ID:var elem=document.getElementById("id值");\
-
- 标签名和* class和name:var elems=document.getElementsByTagName/ClassName/Name("标签名/class名");\
-
2、根据CSS选择器找元素\
-
1、单个元素
var elem=document.queryselector("任意的css选择器");- 强调:万一选择器匹配到多个,只会返回第一个\
-
2、多个元素
var elem=document.querySelectorAll("任意的css选择器");- 强调:找到了返回集合,没找到返回空集合,更适合做复杂查找\
-
-
面试题/笔试题:getXXX和querySelectorAll有什么区别\
-
返回结果不同\
-
1、getXXX:返回的是要给动态集合HTMLCollection\
- 优点:数据始终和DOM树实时挂钩\
- 缺点:每次DOM树进行修改,都会悄悄的再次查找元素,效率相对较低\
-
2、querySelectorAll:返回的是要给静态集合NodeList\
- 优点:每次不会悄悄重新查找,效率较高,而且还支持使用forEach!\
-
-
-
-
DOM\
-
元素的内容\
-
elem.innerHTML
获取或设置开始标签到结束标签之间的HTML代码,没有兼容性问题的可以识别标签- 获取:elem.innerHTML\
- 设置:elem.innerHTML="新内容"\
-
elem.textContent
获取或设置开始标签到结束标签之间的纯文本,有兼容性问题的(老IE不支持),不能识别标签- 获取:elem.textContent\
- 设置:elem.textContent="新内容"\
-
老IE:elem.innerText;\
- 为什么老IE不讲究主流?
微软的,生活中,PC端只有 windows系统 和 MAC系统(土豪),windows系统的使用的人多
- 为什么老IE不讲究主流?
-
input.value
获取或设置表单控件的值 - 只要你做正则验证- 获取:input.value\
- 设置:input.value="新值"\
-
-
元素的属性\
-
获取属性值\
- 核心DOM:elem.getAttribute("属性名");\
- HTML DOM:elem.属性名\
-
设置属性值\
- 核心DOM:elem.setAttribute("属性名","属性值");\
- HTML DOM:elem.属性名="属性值";\
-
删除属性值\
- 核心DOM:elem.removeAttribute("属性名");\
- HTML DOM:elem.属性名=""
删除不推荐使用HTML DOM,删除不干净属性节点,而有的属性,光有属性名就已经具有功能了
-
判断有没有属性\
- 核心DOM:elem.hasAttribute("属性名")
仅仅只能判断有没有这个属性,不能判断出属性值是什么,往往我们自己用获取属性值的操作,获取到了过后再去进行比较运算
- HTML DOM:elem.属性名!="";\
- 核心DOM:elem.hasAttribute("属性名")
-
HTML DOM缺陷\
- 1、class需要写为className\
- 2、不能操作自定义属性\
-
- 元素的样式\
-
-
DOM3\
-
1、创建元素并渲染DOM树(3步)\
-
1、创建空标签\
- var elem=document.createElement("标签名")\
-
2、添加必要的属性和事件\
- elem.属性名="属性值"\
- elem.on事件=function(){}\
- 3、上树:将js内存中的新标签放到DOM树上\
-
- 2、删除元素\
-
-
HTML DOM常用对象:简化【核心DOM】\
-
1、image对象
仅仅是简化了创建语句- 创建:var img=new Image();
var elem=document.createElement("img");
- 注意:不是人人都有构造函数创建方式\
- 创建:var img=new Image();
-
2、form对象
简化了查找元素- 查找form元素:var form=document.forms[i];\
- 查找form元素中的表单控件:var inp=form.elements[i];\
- 专属事件\
-