JS高级程序设计

1 什么是js

1.2 js的实现

完整的js包含3个部分:
  • 核心(ECMAScript):js的统一标准
  • 文档对象模型(DOM)
  • 浏览器对象模型(BOM)

1.2.2 DOM

1.2.3 BOM

BOM 主要针对浏览器窗口和子窗口(frame),不过人们通常会把任何特定于浏览器的扩展都归在 BOM 的范畴内

3.3.3 const 声明

如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制

3.4 数据类型

typeof null 会返回 "object" —— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object

3.4.5 Number 类型

数值转换:
Number函数:
 布尔值,true 转换为 1,false 转换为 0。
 null,返回 0。
 undefined,返回 NaN
 字符串:只包含数值字符,忽略为最前的0,转为数值;空字符串为0;包含十六进制格式如"0xf",转为十六进制;含有其他的则为Nan
parseInt函数:
 从第一个非空格数值字符开始转换,直到末尾或者第一个非数值字符结束
 如果第一字符不是数值字符,直接返回Nan
 parseInt可以自动识别十进制、八进制和十六进制,由于很容易混淆,因此 parseInt()也接收第二个参数,用于指定进制数
parseFloat函数:
 它也是解析到字符串末尾或者解析到一个无效的浮点数值字符为止
 另一个不同之处在于,它始终忽略字符串开头的零。十六进制数值始终会返回 0。因为parseFloat()只解析十进制值,因此不能指定底数。
最后,如果字符串表示整数(没有小数点或者小数点后面只有一个零),则 parseFloat()返回整数
一元运算符:

3.4.7 Symbol 类型

symbol即符号,是ES6新增的数据类型,是唯一的不可变的。它的用途是确保对象的属性是唯一的,不会发生属性冲突的风险。
  • Symbol 是使用带有可选描述(name)的 Symbol() 调用创建的,可选参数与符号定义或标识完全无关
  • 不能和New一起用作构建函数来创建实例
  • Symbol 总是不同的值,即使它们有相同的名字。只有在全局注册表下同名的symbol才会相等:Symbol.for(key) 返回一个以 key 作为名字的全局 Symbol
  • 凡是可以使用字符串或数值作为属性的地方,都可以使用符号----》定义对象属性的几种方法
  • Symbol 属性不会出现在 for..in 中和Object.keys()中,而Object.getOwnPropertySymbols()、Object.getOwnPropertyDescriptors()\Reflect.ownKeys()会返回symbol的键:
  • JavaScript 使用了许多系统 Symbol,例如使用 Symbol.iterator 来进行 迭代 操作

3.5.2 位操作符

负值以一种称为二补数(或补码)的二进制编码存储。一个数值的二补数通过如下 3 个步骤计算:
(1) 确定绝对值的二进制表示(如,对于18,先确定 18 的二进制表示);
(2) 找到数值的一补数(或反码),换句话说,就是每个 0 都变成 1,每个 1 都变成 0;
(3) 给结果加 1。
按位非操作符用波浪符(~)表示,按位非的最终效果是对数值取反并减 1
按位与操作符用和号(&)表示,有两个操作数
按位或操作符用管道符(|)表示,有两个操作数
按位异或用脱字符(^)表示,不同时为1,相同时为0
左移操作符用两个小于号(<<)表示,有符号右移由两个大于号(>>)表示,无符号右移用 3 个大于号表示(>>>)(将负数的二进制表示当成正数的二进制表示来处理)
3.5.4 乘性操作符
+***转成字符串,其他的会转成数字
3.7 函数
不指定返回值的函数实际上会返回特殊值 undefined。
4.2 执行上下文与作用域
所有通过var定义的全局变量或者函数,都会变成全局上下文window的属性和方法
5.1 Date
new Date()方法:
在不给 Date 构造函数传参数的情况下,创建的对象将保存当前日期和时间
要基于其他日期和时间创建日期对象,必须传入其毫秒表示
如果直接把表示日期的字符串传给 Date 构造函数,那么 Date 会在后台调用 Date.parse()
Date.UTC()也会被 Date 构造函数隐式调用,传给 Date.UTC()的参数是年、月(1 月是 0)、日(1~31)、时(0~23)、分、秒和毫秒
Date.now()方法,
返回表示方法执行时日期和时间的毫秒数
5.4.2 Math
把小数值舍入为整数的 方法:
Math.floor()
Math.ceil()
Math.round()-----如果要指定小数位数的话,应该用Num.toFixed(N)
在指定范围内生成一个随机数:Math.floor(Math.rand()*区间大小+初始值)

6.4 Map

6.4.1 基本操作方法

6.4.2 顺序与迭代

  • map.keys() —— 遍历并返回所有的键(returns an iterable for keys),
  • map.values() —— 遍历并返回所有的值(returns an iterable for values),
  • map.entries() —— 遍历并返回所有的实体(returns an iterable for entries)[key, value],for..of 在默认情况下使用的就是这个。
Object.entries 返回键/值对数组:[ ["name","John"], ["age", 30] ]
map.entries() 将返回一个可迭代的键/值对

6.6 set

它的主要特点是,重复使用同一个值调用 set.add(value) 并不会发生什么改变。这就是 Set 里面的每一个值只出现一次的原因。

7.2.1 可迭代协议

实现 Iterable 接口(可迭代协议)要求同时具备两种能力:支持迭代的自我识别能力和创建实现
Iterator 接口的对象的能力。在 ECMAScript 中,这意味着必须暴露一个属性作为“默认迭代器”,而
且这个属性必须使用特殊的 Symbol.iterator 作为键
很多内置类型都实现了 Iterable 接口:
string Array  map  set argumentts nodeList等DOM集合
接收可迭代对象的原生语言特性包括:
 for-of 循环
  数组解构
  扩展操作符
  Array.from()
  创建集合
  创建映射
  Promise.all()接收由期约组成的可迭代对象
  Promise.race()接收由期约组成
yield*操作符,在生成器中使用

8.1.4 合并对象

Object.assign(dest, [src1, src2, src3...])
  • 第一个参数 dest 是指目标对象。
  • 更后面的参数 src1, ..., srcN(可按需传递多个参数)是源对象
对象的深拷贝:
            function deepClone(obj){
                if(obj === null || typeof obj !== Object){
                    return obj
                }
                let res= Array.isArray(obj) ? [] : {}
                for (let i in obj){
                    if(obj.hasOwnProperty(key)){
                        res[key]=deepclone(obj[key])
                    }
                }
            }

8.1.7 对象解构

解构对象:
let {prop : varName = default, ...rest} = object
  • 给解构后的值指定变量名varName
  • 给解构后的值设置默认值
  • 嵌套解构
  • 数组解构

8.2.4 原型模式

function Person() {}
console.log(Person.prototype.__proto__ === Object.prototype); // true 
console.log(Person.prototype.__proto__.constructor === Object); // true 
console.log(Person.prototype.__proto__.__proto__ === null);

console.log(typeof a.prototype);  undefined
console.log(typeof a.__proto__);  Object
a.__proto__=Person.prototype
实例如果不是构造函数的话没有protype属性,只有__proto__,
Object.prototype.prototype在这种情况下Object.prototype也会被当做一个实例没有protype,所以通常用__proto__构建原型链
console.log(typeof Person.prototype);   //Object
console.log(typeof Person.__proto__);  // function
Person.__proto__=== Function.prototype
  • Person.prototype.__proto__ === Object.prototype 原型链严格要严格遵循关系。
Person.prototype看做是Object,从而得到 Person.prototype.__proto__ === Object.__proto__很明显是错误的
  • Object.prototype.__proto__===null
  • Function.__proto__=== Function.prototype
  • 将Object看做是构造函数Object.__proto__===Function.prototype
思考方式时及时替换
8.3 继承
六种继承
8.4.1 类定义
注意区分对象、构造函数和类 
类的方法之间没有逗号,这会导致语法错误。不要把这里的符号与对象字面量相混淆。
两种方式:类声明、类定义
类是由块状作用域控制,且没有变量提升
类的构成:普通属性/方法(前面不需要let,直接=赋值) 静态属性/方法 私有属性/方法 constructor  getter、setter
在把类表达式赋值给变量后,可以通过 name 属性取得类表达式的名称字符串。但不能在类表达式作用域外部访问这个标识符
8.4.2 类构造函数
constructor 在使用 new 操作符创建类的新实例时调用。不定义构造函数相当于将其定义为空函数
类构造函数会在执行之后返回 this 对象,构造函数返回的对象会被用作实例化的对象
调用类构造函数时如果忘了使用 new 则会抛出错误
普通属性/方法(前面不需要let,直接=赋值),可以在实例中使用,不可以在类的构造函数中(普通方法可以通过:类名.prototype.方法  来调用)
constructor定义的属性和方法可以在实例中使用
静态属性/方法  不可以在实例中,可以直接通过构造函数引用
8.4.4 继承
  • super 只能在派生类构造函数和静态方法中使用
  • 不能单独引用 super 关键字,要么用它调用构造函数,要么用它引用静态方法
  • 调用 super()会调用父类构造函数,并将返回的实例赋值给 this
  • super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入
  • 如果没有定义类构造函数,在实例化派生类时会调用 super(),而且会传入所有传给派生类的参数
  • 在类构造函数中,不能在调用 super()之前引用 this
  • 如果在派生类中显式定义了构造函数,则要么必须在其中调用 super(),要么必须在其中返回一个对象
getter和setter不需要提前定义,但是在constructor中对其进行赋值的话,相当于调用set

Mixin 模式

  • 在 JavaScript 中,我们只能继承单个对象。每个对象只能有一个 [[Prototype]]。并且每个类只可以扩展另外一个类。
  • 构造一个拥有实用方法的对象
  •    拷贝方法 Object.assign(User.prototype, sayHiMixin);

11.2 期约

executor(new promise函数) 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject
由 new Promise 构造器返回的 promise 对象具有以下内部属性:
  • state —— 最初是 "pending",然后在 resolve 被调用时变为 "fulfilled",或者在 reject 被调用时变为 "rejected"。
  • result —— 最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error
  • 一个被 executor 完成的工作只能有一个结果或一个 error。并且,resolve/reject 只需要一个参数(或不包含任何参数),并且将忽略额外的参数
  • Promise 对象的 state 和 result 属性都是内部的。我们无法直接访问它们。但我们可以对它们使用 .then/.catch/.finally 方法。
  • promise.then( function(result) {/* handle a successful result */ }, function(error) { /* handle an error */ } );
.then 的第一个参数是一个函数,该函数将在 promise resolved 后运行并接收结果。
.then 的第二个参数也是一个函数,该函数将在 promise rejected 后运行并接收 error。
.catch(f) 调用是 .then(null, f) 的完全的模拟,它只是一个简写形式
finally 是执行清理(cleanup)的很好的处理程序(handler),例如无论结果如何,都停止使用不再需要的加载指示符(indicator)
  • Promise 的(executor)和(handler)周围有一个“隐式的 try..catch”。如果发生异常,就会被捕获,并被视为 rejection 进行处理
  • promise.then的返回的新promise由回调函数的结果决定;

promise.all
promise.race()

12 BOM

12.1 window 对象

window.open()方法可以用于导航到指定 URL,也可以用于打开新浏览器窗口。这个方法接收 4个参数:要加载的 URL、目标窗口、特性字符串
和表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值
//浏览器要设置不拦截弹窗,每次都是重新调试,需要给窗口变量提前赋值到变量,才方便进行下一步操作
对这些属性的使用前面应该加window

14 DOM

14.1 节点层级

任何 HTML 或 XML 文档都可以用 DOM 表示为一个由节点构成的层级结构
document 节点表示每个文档的根节点。在这里,根节点的唯一子节点是<html>元素,我们称之为文档元素。文档元素是文档最外层的元素,所有其他元素都存在于这个元素之内。每个文档只能有一个文档元素。
HTML 中的每段标记都可以表示为这个树形结构中的一个节点,总共有 12 种节点类型

14.1.1 Node 类型

  1. nodeName 与 nodeValue
  2. 节点关系
  3. 访问节点:
    • ownerDocument 返回当前结点的根元素
    • parentNode 
    • childNodes:返回一个NodeList 实例,可以使用中括号访问它的值,而且它也有 length 属性
    • first/lastChild
    • next/previousSibling 返回当前结点之后之前的相邻节点
  4. 操作节点:
  • appendChild
  • cloneNode:传入 true 参数时会进行深复制。传入 false只会复制调用该方法的节点。只复制 HTML 属性及可选地复制子节点。不会复制JavaScript 属性,比如事件处理程序。
  • hasChildNodes
  • insertBefore(要**的节点,位置的节点)
  • normalize 合并相邻的Text节点并删除空的Text节点
  • removeChild
  • replaceChild(要**的节点,要替换的节点)

14.1.2 Document 类型

访问文档(document)子结点(html)的方式有两种,一种是document.documentElement,另一种是document.childNodes[0]
document对象有一个常用的body属性,使用document.body可以访问body元素,!!!其他元素需要使用方法来访问
访问文档元素:
  • getElementById() 区分大小写,如果有多个元素返回第一个
  • getElementsByTagName() 返回NodeList
  • getElementsByName() 返回NodeList
  • getElementsByClassName()
HTML5扩展的一些元素:readyState/head/charset等
文档的写入:这个能力对应 4 个方法:write()、
 writeln()、open()和 close()。其中,write()和 writeln()方法都接收一个字符串参数,可以将这个字符串写入网页中。
write()简单地写入文本,而 writeln()还会在字符串末尾追加一个换行符(\n)。

14.1.3 Element 类型

  • Element 类型的节点具有以下特征:
 nodeType 等于 1;
 nodeName 值为元素的标签名;
 nodeValue 值为 null
  • 所有 HTML 元素上都有的标准属性:
 id,元素在文档中的唯一标识符;
 title,包含元素的额外信息,通常以提示条形式展示;
 lang,元素内容的语言代码(很少用);
 dir,语言的书写方向("ltr"表示从左到右,"rtl"表示从右到左,同样很少用);
 className,相当于 class 属性,用于指定元素的 CSS 类
  • 访问元素---参考访问文档元素
  • 遍历元素---参考Node
  • 设置属性----getAttribute()、setAttribute()和 removeAttribute()
  • 创建元素:document.createElement()
    let c=document.createElement("p")
    c.innerHTML="<p>afd</p>"
    b.appendChild(c)
要把元素添加到文档树,可以使用 appendChild()、insertBefore()或 replaceChild()。把刚才创建的元素添加到文档的<body>元素中
  • 获取焦点元素: document.activeElement

14.1.4 Text 类型

Text 类型的节点具有以下特征:
 nodeType 等于 3;
 nodeName 值为"#text";
 nodeValue 值为节点中包含的文本;
 parentNode 值为 Element 对象;
 不支持子节点。
操作文本的方法:
 appendData(text),向节点末尾添加文本 text;
 deleteData(offset, count),从位置 offset 开始删除 count 个字符;
 insertData(offset, text),在位置 offset ** text;
 replaceData(offset, count, text),用 text 替换从位置 offset 到 offset + count 的文本;
 splitText(offset),在位置 offset 将当前文本节点拆分为两个文本节点;
 substringData(offset, count),提取从位置 offset 到 offset + count 的文本。
1. 创建文本节点
document.createTextNode("<strong>Hello</strong> world!");
Text 类型定义了一个与 normalize()相反的方法——splitText()。这个方法可以在指定的偏移
位置拆分 nodeValue,将一个文本节点拆分成两个文本节点
2 读取HTML字符串
s=node.innerHTML
3 **HTML字符串
node.innerHTML="" ----根据传入的字符串,创建新的代码片段。此时**的<script>标记不会执行
outerHTML在写模式下,会完全替换调用元素(包括标签,例如li)
4 **文本
innerText/outerText

15.1 Selectors API

1 querySelector()
document.querySelector()方法接收CSS选择符参数,返回匹配该模式的第一个后代元素,若没有则返回null
2 querySelectorAll()
它会返回所有匹配的节点,是一个 NodeList 的静态实例
3 matches()
matches()方法接收一个 CSS 选择符参数,如果元素匹配则该选择符返回 true,否则返回 false。
node.matches(CSS选择符参数)
4 元素遍历
IE9 之前的版本不会把元素间的空格当成空白节点,而其他浏览器则会。这样就导致了 childNodes
和 firstChild 等属性上的差异。因此在遍历有两种方法:
  • 遍历,但是对每个节点的nodeType进行判断,是否==1
  • 使用新的方法例如:firsrElementChild

15.3.1 CSS 类扩展

1. getElementsByClassName()
getElementsByClassName()暴露在 document 对象和所有 HTML 元素上,
在 document 上调用返回文档中所有匹配的元素,而在特定元素上调用则返回该元素后代中匹配的元素
2. classList 属性
如果对一个元素的类型进行操作,比如增加删除等:div.classList.add()
 add(value),向类名列表中添加指定的字符串值 value。如果这个值已经存在,则什么也不做。
 contains(value),返回布尔值,表示给定的 value 是否存在。
 remove(value),从类名列表中删除指定的字符串值 value。
 toggle(value),如果类名列表中已经存在指定的 value,则删除;如果不存在,则添加。
3  insertAdjacentHTML()与 insertAdjacentText()

17 事件

JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻。
可以使用仅在事件发生

17.1.3 DOM 事件流

DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,
为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个
阶段响应事件

17.2.1 HTML 事件处理程序

  1. 静态绑定事件:把js代码作为属性值,直接赋予事件属性。
  • <input onclick="console.log('Clicked')"/>
  • 直接调用在页面其他地方定义的事件处理函数
    2. 动态绑定事件:var a = document.getElementById()  a.onclick= function(){}
 对于事件处理函数:
  • 在html属性中使用时,可以用event或者this
  • 在<sctipt>使用时,应该使用event作为参数,如果想使用this,应该用node.onclick=function(){this....}的方式
  • 拿捏不准的时候一律用event
    3. addEventListener()和 removeEventListener()。----使用 addEventListener()添加的匿名函数无法移除
这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:事件名、事件处理函数和一个布尔值,false(默认值)表示在冒泡阶段调用事件处理程序

17.3 事件对象

属性/方法 类型 读/写 说明
bubbles Boolean 只读    表明事件是否冒泡
stopPropagation() Function 只读 取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法
stopImmediatePropagation() Function 只读 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增)
cancelable Boolean 只读 表明是否可以取消事件的默认行为
preventDefault() Function 只读 取消事件的默认行为。如果cancelable是true,则可以使用这个方法
defaultPrevented Boolean 只读 为true表示已经调用了preventDefault()(DOM3级事件中新增)
currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素(currentTarget始终===this,即处理事件的元素
target Element 只读 直接事件目标,真正触发事件的目标
detail Integer 只读 与事件相关的细节信息
eventPhase Integer 只读 调用事件处理程序的阶段:1表示捕获阶段,2表示处于目标阶段,3表示冒泡阶段
type String 只读 被触发的事件的类型
事件委托:把目标节点的事件绑定到他的祖先节点上,这样可以优化代码,提升性能

17.4 事件类型

17.4.1 用户界面事件

 load/unload:在 window 上当页面加载完成后触发,在<img>元素上当图片加载完成后触发,在<object>元素上当相应对象加载完成后触发。
 error:在 window 上当 JavaScript 报错时触发,在<img>元素上当无法加载指定图片时触发,
     在<object>元素上当无法加载相应对象时触发,在窗**当一个或多个窗格无法完成加载时触发。
 select:在文本框(<input>或 textarea)上当用户选择了一个或多个字符时触发。
 resize:在 window 或窗格上当窗口或窗格被缩放时触发。
 scroll:当用户滚动包含滚动条的元素时在元素上触发。<body>元素包含已加载页面的滚动条。

17.4.2 焦点事件

 blur:当元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持。
 focus:当元素获得焦点时触发。这个事件不冒泡,所有浏览器都支持。
 focusin:当元素获得焦点时触发。这个事件是 focus 的冒泡版。
 focusout:当元素失去焦点时触发。这个事件是 blur 的通用版。

17.4.3 鼠标和滚轮事件

 click:在用户单击鼠标主键(通常是左键)或按键盘回车键时触发。
 dblclick:在用户双击鼠标主键(通常是左键)时触发。
 mousedown:在用户按下任意鼠标键时触发。这个事件不能通过键盘触发。
 mousemove:在鼠标光标在元素上移动时反复触发。这个事件不能通过键盘触发。
 mouseout:在用户把鼠标光标从一个元素移到另一个元素上时触发。移到的元素可以是原始元
                       素的外部元素,也可以是原始元素的子元素。这个事件不能通过键盘触发。
 mouseover:在用户把鼠标光标从元素外部移到元素内部时触发。这个事件不能通过键盘触发。
  • 对 mouseover 事件来说,事件的主要目标是获得光标的元素,相关元素是失去光标的元素。
  • 类似地,对 mouseout 事件来说,事件的主要目标是失去光标的元素,而相关元素是获得光标的元素
 mouseup:在用户释放鼠标键时触发。这个事件不能通过键盘触发。
  • 除了 mouseenter 和 mouseleave,所有鼠标事件都会冒泡,都可以被取消,而这会影响浏览器的默认行为
  • 鼠标事件都是在浏览器视口中的某个位置上发生的。这些信息被保存在 event 对象的 clientX 和clientY 属性中(页面坐标pageX/Y  页面坐标screenX/Y 距离目标对象坐标offsetX/Y)

17.4.4 键盘与输入事件

 keydown,用户按下键盘上某个键时触发,而且持续按住会重复触发。
 keypress,用户按下键盘上某个键并产生字符时触发,而且持续按住会重复触发。Esc 键也会
触发这个事件。DOM3 Events 废弃了 keypress 事件,而推荐 textInput 事件。
 keyup,用户释放键盘上某个键时触发。
  • 对于 keydown 和 keyup 事件,event 对象的 keyCode 属性中会保存一个键码,对应键盘上特定的一个键
  • shiftKey/altKey/ctrKey可以在event事件中存在(返回值为布尔值),而其他键盘事件属性在时间发生后才会存在于事件对象
17.6.1 DOM 事件模拟

18.3 2D 绘图上下文
ctx.font="10px bold" 赋值时不需要分号
ctx.lineWidth=10<!--赋值时用的数字形式而不是字符串-->

全部评论

相关推荐

点赞 评论 收藏
分享
迈瑞 智能产线的上位机软件和算法 总包31w, 最低32w 硕士
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务