垃圾回收机制

最后更新于:2022-04-01 23:55:12

##垃圾收集## **3. 垃圾收集** JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。 垃圾收集机制的原理:找出那些不再继续使用的变量,然后释放其占用的内存。 垃圾收集器是按固定的时间间隔,周期性地执行回收操作。 垃圾收集器如何判断哪些变量不需要使用了呢?常见的有两种方式 **(1)标记清除** 当变量进入环境(比如在函数中声明一个变量)时,就将这个变量标记为“进入环境”。 标记变量的方式可以是任意的。 垃圾收集器在运行时会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记,而在此之后再被标记的变量将被视为待删除的变量,原因是环境中的变量以及无法访问到这些变量了,最后完成内存清除工作,销毁那些带标记的值并回收它们占用的内存空间。 **(2) 引用计数** 引用计数是不太常见的垃圾收集策略。引用计数可以说是跟踪记录每个值被引用的次数。比如:当声明了一个变量并将一个引用类型值赋给变量时,则这个值的引用次数是1,当同一个值又被赋给另一个变量,则该值的引用次数加1,相反,当包含对这个值引用的变量取得了另外一个值(也就是不指向前面的值)时,这个值的引用次数减1,当这个值的引用次数为0时,就会被销毁并释放内存空间了。 解除引用:一旦数据不再有用,最好通过将其值设置为null来释放其引用。
';

编程风格

最后更新于:2022-04-01 23:55:10

## 编风格程 作为前端开发人员,我相信每一个人都或多或少的用到原生的JavaScript,也正是因为用的人多,导致编码风格也是多种多样的,而不规范的编码风格,不仅会导致一些奇怪的问题出现,而且不利于后期维护和提高执行效率。 基于本人也在开发中因为规范而出现各种问题,我特意的整理了一下JavaScript编码规范(并不强制,只是推荐)。 **1、变量** 声明变量必须加上`var`关键字,而且每个`var`只声明一个变量,增加可读写。 推荐: ``` var name = 'TG'; var sex = 'man'; ``` 不推荐: ``` var name = 'TG', sex = 'man'; ``` **2、常量** 常量的命名方式:用大写字符,并用下划线分隔。尽量不要使用const关键词。 ``` var MY_NAME = 'TG'; ``` 原因:IE并不支持const **3、行尾分号** 总是使用分号,对于可用可不用的行尾分号,使用分号。 **4、嵌套函数** 可以使用,可以减少重复代码,隐藏帮助函数等好处 **5、块内函数声明** 不要在块内声明一个函数 不推荐: ``` if(a){ function foo(){} } ``` 推荐: ``` if(a){ var foo = function(){} } ``` **6、异常处理** 可以使用 ``` try{}catch(e){} throw exception ``` **7、eval()** ``` 只用于解析序列化串 ``` 原因:eval()会让程序执行的比较混乱。 **8、with(){}** 尽量少用。 **9、缩进** 用4个空格作为一缩进,而不是使用tab 原因:因为在不同浏览器上,tab的长度不一。 **10、字符串过长截取** 每行代码不超过80个字符。如代码过长,可使用+运算符拼接。 原因:过长会导致需要拖动横向滚动条才看得到后面的代码,降低开发效率,而且在复制黏贴时有可能错漏。 **11、大括号** 区块起首的大括号,不要另起一行 推荐: ``` if (true) { } ``` 不推荐: ``` if (true) { } ``` **12、构造函数** 对于构造函数,命名采用首字母大写,其他函数一律小写。 原因:可读性,区分构造函数和普通函数 **13、注释** 合理的加上注释,有利于后期维护,提高可读性。 **14、{}和[]** 使用{}代替new Object(),使用[]代替new Array() **15、单引号(')** 尽量使用单引号('),只在JSON文件中使用双引号。 **16、变量和函数声明** 变量名和函数名在JavaScript机制下会发生声明提升(也就是会提前到顶部声明),所以建议变量和函数应该在使用前声明。 **17、使用===和!==代替==和!=** 在JavaScript中,比较运算符进行计算时会进行强制转换,==和!=会产生一些意想不到的结果,所以应该用“严格相等”===。 **18、换行** 在语句块和下一个语句之间留一个空行,提高可读性。 **19、命名** 构造函数或类名使用驼峰式命名 **20、嵌入规则** JavaScript程序应该尽量放在.js的文件中。 **21、命名规则** JavaScript 中的标识符的命名规则: 以字母、下划线'_'或美元符号'$'开头 允许名称中包含字母,数字,下划线'_'和美元符号'$' 区分大小写 变量、属性和函数名应该用驼峰式: ``` var isLogin = false; ``` 私有函数用下划线开头: ``` function getFirstName(){ function _getName(){} } ``` 构造函数和类名应该首字母大写。 对象中私有变量和函数以下划线开头。 **22、语句** 对于复合语句,if, for, while, do, switch, try … catch 等代码体,函数定义的函数体,对象的定义等都需要放在花括号'{}'里面。 '{' 应在行末,标志代码块的开始。 '}' 应在一行开头,标志代码块的结束,同时需要和'{'所在行的开始对齐,以表明一个完整的复合语句段。这样可以极大地提高代码的可阅读性,控制逻辑能清晰地表现出来。 被包含的代码段应该再缩进 4 个空格。 即使被包含的代码段只有一句,也应该用花括号'{}'包含。尽管不用花括号代码也不会错,但如若需要增加语句的话,则较容易因花括号遗漏而引起的编译错误或逻辑错误。 return语句在使用时也需注意,如果用表达式的执行作为返回值,应该把表达式和 return 放在同一行中,以免换行符被误解析为语句的结束而引起返回错误。return 关键字后若没有返回表达式,则返回 undefined。构造器的默认返回值为 this。 return a + b; **23、方法链(调用链)** 如果使用方法链,应该每行只调用一个方法: Animal .getName() .getFirstName() **24、使用三元运算符** 三元运算符不应该用在一行,应该分割成多行替代。 推荐: ``` var foo = (a === b) ? 1 : 2; ``` 不推荐: ``` var foo = (a === b) ?1 : 2; ``` **25、逗号** 对于数组和对象不要使用多余的“,” 不推荐: ``` var arr = [1,2,] var person = { name: 'TG' }; ``` 原因:IE不兼容 **26、for-in** 对于数组,尽量避免使用for-in
';

JavaScript开发技巧合集

最后更新于:2022-04-01 23:55:08

## 开发技巧 **1、使用var声明变量** 如果给一个没有声明的变量赋值,默认会作为一个全局变量(即使在函数内赋值)。要尽量避免不必要的全局变量。 **2、行尾使用分号** 虽然JavaScript允许省略行尾的分号,但是有时不注意的省略,会导致不必要的错误。建议在可用可不用行尾分号的地方加上分号。 **3、获取指定范围内的随机数** ``` var getRandom = function(max, min) { min = arguments[1] || 0; return Math.floor(Math.random() * (max - min + 1) + min); }; ``` 上面的函数接受一个你希望的随机最大数和一个你希望的随机最小数。 **4、打乱数字数组的顺序** ``` var sortArray = array.sort(function(){ return Math.random() - 0.5; }); ``` **5、取出数组中的随机项** ``` var ran = array[Math.floor(Math.random() * array.length)]; ``` **6、去除字符串的首尾空格** ``` var s = string.trim(); ``` **7、类数组对象转为数组** 比如:类数组对象遍历: ``` Array.prototype.forEach.call(argumens,function(value){ }) ``` DOM的NodeList和HTMLCollection也是类数组对象 **8、获取数组中的最大值和最小值** ``` var max = Math.max.apply(Math, array); var min = Math.min.apply(Math, array); ``` **9、清空数组** array.length = 0; array = []; **10、保留指定小数位** ``` var num = num.toFixed(2); ``` 返回字符串,保留两位小数 **11、使用for-in循环来遍历对象的属性** ``` for(var key in object) { // object[key] } ``` 不要用for-in来遍历数据 **12、获取某月天数** ``` function getMonthDay(date){ date = date || new Date(); if(typeof date === 'string') { date = new Date(date); }; date.setDate(32); return 32 - date.getDate(); } ``` 传入date参数,可以是字符串、日期对象实例;为空表示当月天数 **13、浮点数问题** ``` 0.1 + 0.2 = 0.30000000000000004 != 0.3 ``` JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示 **14、JSON序列化和反序列化** 使用`JSON.stringify()`来将JavaScript对象序列化为有效的字符串。 使用`JSON.parse()`来将有效的字符串转换为JavaScript对象。 在AJAX传输数据时很有用 **15、使用“===”替换“==”** 相等运算符(==)在比较时会将操作数进行相应的类型转换,而全等运算符(===)不会进行类型转换。 **16、避免使用with()** 使用with()可以把变量加入到全局作用域中,因此,如果有其它的同名变量,一来容易混淆,二来值也会被覆盖。 **17、不要使用eval()或函数构造器** eval()和函数构造器(Function consturctor)的开销较大,每次调用,JavaScript引擎都要将源代码转换为可执行的代码。 **18、简化if语句** ``` if (condition) { fn(); } ``` 可替换成: ``` condition && fn(); ``` **19、给可能省略的参数赋默认值** ``` function test(a, b){ a = a || '1'; } ``` **20、给数组循环中缓存length的值** 如果你确定循环中数组的长度不会变化,那么你可以这样: ``` var length = array.length; for(var i = 0; i < length; i++) { } ``` 可以避免在每次迭代都将会重新计算数组的大小,提高效率 **21、合并数组** 对于小数组,我们可以这样: ``` var arr1 = [1,2,3]; var arr2 = [4,5,6]; var arr3 = arr1.concat(arr2); // [1,2,3,4,5,6] ``` 不过,concat()这个函数并不适合用来合并两个大型的数组,因为其将消耗大量的内存来存储新创建的数组。在这种情况之个,可以使用`Array.prototype.push.apply(arr1,arr2)`来替代创建一个新数组。 这种方法不是用来创建一个新的数组,其只是将第一个第二个数组合并在一起,同时减少内存的使用: ``` Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [1,2,3,4,5,6] ``` **22 枚举对象“自身”的属性** for...in除了枚举对象“自身”的属性外,还会枚举出继承过来的属性。 ``` var hasOwn = Object.prototype.hasOwnProperty; var obj = {name: 'tg', age: 24}; for(var name in obj) { if (hasOwn.call(obj, name)) { console.log(name + ':' + obj[name]); } } // name:tg // age:24 ```
';

错误处理机制

最后更新于:2022-04-01 23:55:05

## 错误处理机制 **1、 try-catch语句** ECMA-262第3版引入了`try-catch`语句,作为JavaScript中处理异常的一种标准方式。 语法: ``` try{ // 可能会导致错误的代码 }catch (error){ // 在错误发生时怎么处理 } ``` 也就是说,我们应该把所有可能会抛出错误的代码都放在try语句块中,而把那些用于错误处理代码放在catch块中。 `try-catch`语句的逻辑是:如果try块中的任何代码发生了错误,就会立即退出代码执行过程,然后接着执行catch块。此时,catch块会接收到一个包含错误信息的对象。 注意:即使你不想使用这个错误对象,也要给它起个名字。 虽然这个对象在不同浏览器中可能包含不同信息,但是都有一个保存着错误消息的message属性,还有一个保存错误类型的name属性(并不是所有浏览器都有)。 ``` try{ }catch (error){ console.log(error.message); } ``` 在跨浏览器编程时,最好还是只使用message属性。 **1.1 finally子句** 当使用`finally`子句时,其代码无论如何都会执行,也就是说,不管是正常执行还是出错了,`finally`子句都会执行。甚至`return`语句,也不会阻止`finally`子句的执行。 看下面的例子: ``` function test(){ try{ console.log('a'); return 2; }catch(error){ console.log('b'); }finally{ console.log('c'); } } console.log(test()); //结果 a c 2 ``` 从运行结果,我们可以看到,`return`语句并没有阻止`finally`子句的执行,而且是在`finally`子句执行后才会返回`return`语句的值。 **2、错误类型** 执行代码期间可能会发生的错误有多种类型。每种错误都有对应的错误类型,而当错误发生时,会抛出相应类型的错误对象。 ECMA-262定义了下列7中错误类型: ``` Error EvalError RangeError ReferenceError SyntaxError TypeError URIError ``` Error是基类型,其他错误类型都继承自该类型。所有错误类型共享了一组相同的属性。 **(1)EvalError类型** EvalError类型的错误会在使用eval()函数而发生异常时抛出。简单的说,如果没有把eval()当成函数调用,就会抛出异常。比如: ``` new eval() // 抛出EvalError eval = foo; // 抛出EvalError ``` 注意:在ES5中已经不在出现了。 **(2)RangeError类型** RangeError类型的错误会在数值超出相应范围时触发。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。 ``` var item = new Array(-20); // 抛出RangeError异常 ``` **(3)ReferenceError类型** 在找不到对象的情况下,会发生ReferenceError。通常,在访问不存在的变量时,就会发生这种错误。 ``` var obj = x; // 在x并未声明的情况下抛出ReferenceError ``` **(4)SyntaxError类型** SyntaxError是解析代码时发生的语法错误。 ``` var 1a; // 变量名错误,抛出SyntaxError ``` **(5)TypeError类型** 在变量中保存着意外的类型,或在访问不存在的方法时,都会导致这种错误。 ``` var o = new 10; //抛出TypeError ``` **(6)URIError类型** URIError是URI相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。 **2.2 抛出错误** 与try-catch语句相配的还有一个throw操作符,用于随时抛出自定义错误。抛出错误时,必须要给throw操作符指定一个值,这个值可以是任何类型。 ``` throw 1; throw 'tg'; throw true; throw {name: 'tg'}; ``` 上面的代码都是有效的。 在遇到throw操作符时,代码会立即停止运行。仅当有try-catch语句捕获到被抛出的值时,代码才会继续执行。 **2.3 Error对象** 所有抛出的错误都是Error构造函数的实例。Error构造函数接受一个参数,表示错误提示,可以从实例的message属性读到这个参数。 在JavaScript中,Error对象的实例必须有message属性,表示出错时的提示信息。在大多数JavaScript引擎中,Error实例还可能有name和stack属性,分别表示错误的名称和错误的堆栈。 ``` var err = new Error('出错了'); err.message; // "出错了" ``` **2.4 自定义错误** 我们还可以创建自定义错误消息,最常用的错误类型是Error、RangeError、ReferenceError和TypeError。 ``` throw new Error('报错了'); throw new RangeError('数组长度错误'); ``` 另外,利用原型链还可以通过继承Error来创建自定义错误类型: ``` function CustomError(message){ this.name = 'CustomError'; this.message = message; } CustomError.prototype = new Error(); throw new CustomError('我的错误信息'); ``` **3、错误(error)事件** 任何没有通过try-catch处理的错误都会触发window对象的error事件。 onerror事件处理程序不会创建event对象,但它接受三个参数:错误消息、错误所在的URL和行号。 ``` window.onerror = function(message, url, line){ }; ``` 当你在事件处理程序中返回false,可以阻止浏览器报告错误的默认行为 ``` window.onerror = function(message, url, line){ return false; }; ``` **4、调试技术** **4.1 alert方法** 在以前,大多数都是在要调试的代码中插入alert()函数,看是否执行到这一步来判断哪里出错,这种方式比较麻烦,因为alert()会阻止后续代码的执行(除非你关闭了alert弹窗),而且调试后还要清理。 **4.2 console** 随着浏览器的不断改善,现在的浏览器都有JavaScript控制台,我们可以向这些控制台输出消息,比如最常用的console对象,它的常用方法如下: - error(message):将错误消息记录到控制台 - info(message):将信息性消息记录到控制台 - log(message):将一般消息记录到控制台 - warn(message):将警告消息记录到控制台 ``` function test(){ console.log('结果:' + (1 + 2)); } ``` **4.3 throw** 使用throw抛出错误。
';

SVG

最后更新于:2022-04-01 23:55:03

## SVG:可伸缩的矢量图形 这里只是简要的介绍一下SVG,如要深入,推荐看《SVG经典入门》 **1、SVG** **1.1 概述** SVG是一种用于描述图形的XML语法。由于结构是XML格式,使得它可以插入HTML文档,成为DOM的一部分,然后用JavaScript和CSS进行操作。 一个简单的SVG文件如下: ``` ``` **1.2 使用方法** 要使用SVG有很多方法,最简单的就是直接将SVG代码嵌入到HTML中: ``` ``` SVG代码也可以单独写在一个文件中,后缀是“.svg”,然后用在` ``` **1.3 基本图形** **(1)矩形** ``` ``` 属性说明: rect 元素的 `width` 和 `height` 属性可定义矩形的高度和宽度 `style` 属性用来定义 CSS 属性 - fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值) - fill-opacity属性定义填充颜色的透明度 - stroke-width 属性定义矩形边框的宽度 - stroke 属性定义矩形边框的颜色 - stroke-opacity属性定义笔触颜色的透明度 - opacity属性定义元素的透明度 - rx和ry属性定义矩形圆角 下面的其他图形都支持style属性,而且可以单独作为属性添加。 **(2)圆形** ``` ``` 属性说明: - cx和cy属性定义圆点的x和y坐标,如果省略,则默认为(0,0) - r属性定义圆的半径 **(3)椭圆** ``` ``` 属性说明: - cx和cy属性定义椭圆的中心的x和y坐标 - rx定义水平半径 - ry定义垂直半径 **(4)直线** ``` ``` 属性说明: - x1和y1表示起始点的x和y坐标 - x2和y2表示结束点的x和y坐标 **(5)多边形** ``` ``` 属性说明: - points属性定义多边形每个角的x和y坐标,x和y坐标之间用逗号隔开,每个坐标点之间用空格隔开 **(6)曲线** ``` ``` - points属性定义多边形每个角的x和y坐标,x和y坐标之间用逗号隔开,每个坐标点之间用空格隔开 **(7)文本** ``` I love SVG ``` **(8)路径** ``` ``` 属性说明: - d属性定义一组路径数据,一对坐标值的x和y坐标之间可以用空格或逗号隔开,但坐标对与坐标对之间只能用空格分隔。 - pathLength属性定义路径总长度,不允许负值 绘图指令: ``` M moveto,表示移动,后跟着坐标点,比如150 0 L lineto,表示连接(也可以说是绘制直线),后跟着坐标点,比如75 200 H horizontal lineto,绘制水平线段 V vertical lineto,绘制垂直线段 C curveto,绘制普通的三次贝塞尔曲线(C x1 y1 x2 y2 destx desty) S smooth curveto:绘制光滑的三次贝塞尔曲线(S x2 y2 destx desty) Q quadratic Bézier curve:绘制普通的二次贝塞尔曲线 T smooth quadratic Bézier curveto:绘制光滑的二次贝塞尔曲线 A elliptical Arc:绘制椭圆弧 Z closepath,表示完成闭合路径,即将路径首尾相连,构成闭合图形 ``` 大写表示绝对定位,小写表示相对定位。 **1.4 装饰SVG** **1.4.1 stroke属性** - stroke:定义一条线,文本或元素轮廓颜色 - stroke-width:定义了一条线,文本或元素轮廓厚度 - stroke-linecap:定义不同类型的开放路径的终结(可能值:butt、round、square) - stroke-dasharray:用于创建虚线 **1.4.2 滤镜** **(1)模糊效果** 所有的SVG滤镜都定义在``元素中, ``标签用来定义SVG滤镜 例子:`` 元素是用于创建模糊效果 ``` ``` **(2)阴影** ``元素是用于创建阴影效果。 ``` ``` **1.4.3 渐变** **(1)线性渐变** ``元素用于定义线性渐变。 ``` ``` **(2)放射性渐变** ``元素用于定义放射性渐变。 ``` ``` ';

常用API合集

最后更新于:2022-04-01 23:55:01

## 常用API合集 **一、节点** **1.1 节点属性** ``` Node.nodeName //返回节点名称,只读 Node.nodeType //返回节点类型的常数值,只读 Node.nodeValue //返回Text或Comment节点的文本值,只读 Node.textContent //返回当前节点和它的所有后代节点的文本内容,可读写 Node.baseURI //返回当前网页的绝对路径 Node.ownerDocument //返回当前节点所在的顶层文档对象,即document Node.nextSibling //返回紧跟在当前节点后面的第一个兄弟节点 Node.previousSibling //返回当前节点前面的、距离最近的一个兄弟节点 Node.parentNode //返回当前节点的父节点 Node.parentElement //返回当前节点的父Element节点 Node.childNodes //返回当前节点的所有子节点 Node.firstChild //返回当前节点的第一个子节点 Node.lastChild //返回当前节点的最后一个子节点 //parentNode接口 Node.children //返回指定节点的所有Element子节点 Node.firstElementChild //返回当前节点的第一个Element子节点 Node.lastElementChild //返回当前节点的最后一个Element子节点 Node.childElementCount //返回当前节点所有Element子节点的数目。 ``` **1.2 操作** ``` Node.appendChild(node) //向节点添加最后一个子节点 Node.hasChildNodes() //返回布尔值,表示当前节点是否有子节点 Node.cloneNode(true); // 默认为false(克隆节点), true(克隆节点及其属性,以及后代) Node.insertBefore(newNode,oldNode) // 在指定子节点之前插入新的子节点 Node.removeChild(node) //删除节点,在要删除节点的父节点上操作 Node.replaceChild(newChild,oldChild) //替换节点 Node.contains(node) //返回一个布尔值,表示参数节点是否为当前节点的后代节点。 Node.compareDocumentPosition(node) //返回一个7个比特位的二进制值,表示参数节点和当前节点的关系 Node.isEqualNode(noe) //返回布尔值,用于检查两个节点是否相等。所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。 Node.normalize() //用于清理当前节点内部的所有Text节点。它会去除空的文本节点,并且将毗邻的文本节点合并成一个。 //ChildNode接口 Node.remove() //用于删除当前节点 Node.before() // Node.after() Node.replaceWith() ``` **1.3 Document节点** **1.3.1 Document节点的属性** ``` document.doctype // document.documentElement //返回当前文档的根节点 document.defaultView //返回document对象所在的window对象 document.body //返回当前文档的节点 document.head //返回当前文档的节点 document.activeElement //返回当前文档中获得焦点的那个元素。 //节点集合属性 document.links //返回当前文档的所有a元素 document.forms //返回页面中所有表单元素 document.images //返回页面中所有图片元素 document.embeds //返回网页中所有嵌入对象 document.scripts //返回当前文档的所有脚本 document.styleSheets //返回当前网页的所有样式表 //文档信息属性 document.documentURI //表示当前文档的网址 document.URL //返回当前文档的网址 document.domain //返回当前文档的域名 document.lastModified //返回当前文档最后修改的时间戳 document.location //返回location对象,提供当前文档的URL信息 document.referrer //返回当前文档的访问来源 document.title //返回当前文档的标题 document.characterSet属性返回渲染当前文档的字符集,比如UTF-8、ISO-8859-1。 document.readyState //返回当前文档的状态 document.designMode //控制当前文档是否可编辑,可读写 document.compatMode //返回浏览器处理文档的模式 document.cookie //用来操作Cookie ``` **1.3.2 Document节点的方法** **(1)读写方法** ``` document.open() //用于新建并打开一个文档 document.close() //不安比open方法所新建的文档 document.write() //用于向当前文档写入内容 document.writeIn() //用于向当前文档写入内容,尾部添加换行符。 ``` **(2)查找节点** ``` document.querySelector(selectors) //接受一个CSS选择器作为参数,返回第一个匹配该选择器的元素节点。 document.querySelectorAll(selectors) //接受一个CSS选择器作为参数,返回所有匹配该选择器的元素节点。 document.getElementsByTagName(tagName) //返回所有指定HTML标签的元素 document.getElementsByClassName(className) //返回包括了所有class名字符合指定条件的元素 document.getElementsByName(name) //用于选择拥有name属性的HTML元素(比如
、、等) document.getElementById(id) //返回匹配指定id属性的元素节点。 document.elementFromPoint(x,y) //返回位于页面指定位置最上层的Element子节点。 ``` **(3)生成节点** ``` document.createElement(tagName) //用来生成HTML元素节点。 document.createTextNode(text) //用来生成文本节点 document.createAttribute(name) //生成一个新的属性对象节点,并返回它。 document.createDocumentFragment() //生成一个DocumentFragment对象 ``` **(4)事件方法** ``` document.createEvent(type) //生成一个事件对象,该对象能被element.dispatchEvent()方法使用 document.addEventListener(type,listener,capture) //注册事件 document.removeEventListener(type,listener,capture) //注销事件 document.dispatchEvent(event) //触发事件 ``` **(5)其他** ``` document.hasFocus() //返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。 document.adoptNode(externalNode) //将某个节点,从其原来所在的文档移除,插入当前文档,并返回插入后的新节点。 document.importNode(externalNode, deep) //从外部文档拷贝指定节点,插入当前文档。 ``` **1.4 Element节点** **1.4.1 Element节点的属性** **(1)特性属性** ``` Element.attributes //返回当前元素节点的所有属性节点 Element.id //返回指定元素的id属性,可读写 Element.tagName //返回指定元素的大写标签名 Element.innerHTML //返回该元素包含的HTML代码,可读写 Element.outerHTML //返回指定元素节点的所有HTML代码,包括它自身和包含的的所有子元素,可读写 Element.className //返回当前元素的class属性,可读写 Element.classList //返回当前元素节点的所有class集合 Element.dataset //返回元素节点中所有的data-*属性。 ``` **(2)尺寸属性** ``` Element.clientHeight //返回元素节点可见部分的高度 Element.clientWidth //返回元素节点可见部分的宽度 Element.clientLeft //返回元素节点左边框的宽度 Element.clientTop //返回元素节点顶部边框的宽度 Element.scrollHeight //返回元素节点的总高度 Element.scrollWidth //返回元素节点的总宽度 Element.scrollLeft //返回元素节点的水平滚动条向右滚动的像素数值,通过设置这个属性可以改变元素的滚动位置 Element.scrollTop //返回元素节点的垂直滚动向下滚动的像素数值 Element.offsetHeight //返回元素的垂直高度(包含border,padding) Element.offsetWidth //返回元素的水平宽度(包含border,padding) Element.offsetLeft //返回当前元素左上角相对于Element.offsetParent节点的垂直偏移 Element.offsetTop //返回水平位移 Element.style //返回元素节点的行内样式 ``` **(3)节点相关属性** ``` Element.children //包括当前元素节点的所有子元素 Element.childElementCount //返回当前元素节点包含的子HTML元素节点的个数 Element.firstElementChild //返回当前节点的第一个Element子节点 Element.lastElementChild //返回当前节点的最后一个Element子节点 Element.nextElementSibling //返回当前元素节点的下一个兄弟HTML元素节点 Element.previousElementSibling //返回当前元素节点的前一个兄弟HTML节点 Element.offsetParent //返回当前元素节点的最靠近的、并且CSS的position属性不等于static的父元素。 ``` **1.4.2 Element节点的方法** **(1)位置方法** ``` getBoundingClientRect() // getBoundingClientRect返回一个对象,包含top,left,right,bottom,width,height // width、height 元素自身宽高 // top 元素上外边界距窗口最上面的距离 // right 元素右外边界距窗口最上面的距离 // bottom 元素下外边界距窗口最上面的距离 // left 元素左外边界距窗口最上面的距离 // width 元素自身宽(包含border,padding) // height 元素自身高(包含border,padding) getClientRects() //返回当前元素在页面上形参的所有矩形。 // 元素在页面上的偏移量 var rect = el.getBoundingClientRect() return { top: rect.top + document.body.scrollTop, left: rect.left + document.body.scrollLeft } ``` **(2)属性方法** ``` Element.getAttribute():读取指定属性 Element.setAttribute():设置指定属性 Element.hasAttribute():返回一个布尔值,表示当前元素节点是否有指定的属性 Element.removeAttribute():移除指定属性 ``` **(3)查找方法** ``` Element.querySelector() Element.querySelectorAll() Element.getElementsByTagName() Element.getElementsByClassName() ``` **(4)事件方法** ``` Element.addEventListener():添加事件的回调函数 Element.removeEventListener():移除事件监听函数 Element.dispatchEvent():触发事件 //ie8 Element.attachEvent(oneventName,listener) Element.detachEvent(oneventName,listener) // event对象 var event = window.event||event; // 事件的目标节点 var target = event.target || event.srcElement; // 事件代理 ul.addEventListener('click', function(event) { if (event.target.tagName.toLowerCase() === 'li') { console.log(event.target.innerHTML) } }); ``` **(5)其他** ``` Element.scrollIntoView() //滚动当前元素,进入浏览器的可见区域 //解析HTML字符串,然后将生成的节点插入DOM树的指定位置。 Element.insertAdjacentHTML(where, htmlString); Element.insertAdjacentHTML('beforeBegin', htmlString); // 在该元素前插入 Element.insertAdjacentHTML('afterBegin', htmlString); // 在该元素第一个子元素前插入 Element.insertAdjacentHTML('beforeEnd', htmlString); // 在该元素最后一个子元素后面插入 Element.insertAdjacentHTML('afterEnd', htmlString); // 在该元素后插入 Element.remove() //用于将当前元素节点从DOM中移除 Element.focus() //用于将当前页面的焦点,转移到指定元素上 ``` **二、CSS操作** **(1)类名操作** ``` //ie8以下 Element.className //获取元素节点的类名 Element.className += ' ' + newClassName //新增一个类名 //判断是否有某个类名 function hasClass(element,className){ return new RegExp(className,'gi').test(element.className); } //移除class function removeClass(element,className){ element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'),''); } //ie10 element.classList.add(className) //新增 element.classList.remove(className) //删除 element.classList.contains(className) //是否包含 element.classList.toggle(className) //toggle class ``` **(2)style操作** ``` element.setAttribute('style','') element.style.backgroundColor = 'red' element.style.cssText //用来读写或删除整个style属性 element.style.setProperty(propertyName,value) //设置css属性 element.style.getPropertyValue(property) //获取css属性 element.style.removeProperty(property) //删除css属性 操作非内联样式 //ie8 element.currentStyle[attrName] //ie9+ window.getComputedStyle(el,null)[attrName] window.getComputedStyle(el,null).getPropertyValue(attrName) //伪类 window.getComputedStyle(el,':after')[attrName] ``` **三、对象** **3.1 Object对象** **(1)生成实例对象** ``` var o = new Object() ``` **(2)属性** ``` Object.prototype //返回原型对象 ``` **(3)方法** ``` Object.keys(o) //遍历对象的可枚举属性 Object.getOwnPropertyName(o) //遍历对象不可枚举的属性 ``` 对象实例的方法 ``` valueOf():返回当前对象对应的值。 toString():返回当前对象对应的字符串形式。 toLocaleString():返回当前对象对应的本地字符串形式。 hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。 isPrototypeOf():判断当前对象是否为另一个对象的原型。 propertyIsEnumerable():判断某个属性是否可枚举。 ``` **3.2 Array对象** **(1)生成实例对象** ``` var a = new Array() ``` **(2)属性** ``` a.length //长度 ``` **(3)Array.isArray()** ``` Array.isArray(a) //用来判断一个值是否为数组 ``` **(4)Array实例的方法** ``` a.valueof() //返回数组本身 a.toString() //返回数组的字符串形式 a.push(value,vlaue....) //用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。 pop() //用于删除数组的最后一个元素,并返回该元素 join() //以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔。 concat() //用于多个数组的合并。它将新数组的成员,添加到原数组的尾部,然后返回一个新数组,原数组不变。 shift() //用于删除数组的第一个元素,并返回该元素。 unshift(value) //用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。 reverse() //用于颠倒数组中元素的顺序,返回改变后的数组 slice(start_index, upto_index); //用于提取原数组的一部分,返回一个新数组,原数组不变。第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员。负数表示倒数第几个。 splice(index, count_to_remove, addElement1, addElement2, ...); //用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。 sort() //对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数,表示按照自定义方法进行排序。该函数本身又接受两个参数,表示进行比较的两个元素。如果返回值大于0,表示第一个元素排在第二个元素后面;其他情况下,都是第一个元素排在第二个元素前面。 map() //对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组。 map(elem,index,arr) //map方法接受一个函数作为参数。该函数调用时,map方法会将其传入三个参数,分别是当前成员、当前位置和数组本身。 forEach() //遍历数组的所有成员,执行某种操作,参数是一个函数。它接受三个参数,分别是当前位置的值、当前位置的编号和整个数组。 filter() //参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。 some() //用来判断数组成员是否符合某种条件。接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值。该函数接受三个参数,依次是当前位置的成员、当前位置的序号和整个数组。只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false。 every() //用来判断数组成员是否符合某种条件。接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值。该函数接受三个参数,依次是当前位置的成员、当前位置的序号和整个数组。所有数组成员的返回值都是true,才返回true,否则false。 reduce() //依次处理数组的每个成员,最终累计为一个值。从左到右处理(从第一个成员到最后一个成员) reduceRight() //依次处理数组的每个成员,最终累计为一个值。从右到左(从最后一个成员到第一个成员) indexOf(s) //返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。可以接受第二个参数,表示搜索的开始位置 lastIndexOf() //返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。 ``` **3.3 Number对象** **(1)生成对象** ``` var n = new Number() ``` **(2)Number对象的属性** ``` Number.POSITIVE_INFINITY:正的无限,指向Infinity。 Number.NEGATIVE_INFINITY:负的无限,指向-Infinity。 Number.NaN:表示非数值,指向NaN。 Number.MAX_VALUE:表示最大的正数,相应的,最小的负数为-Number.MAX_VALUE。 Number.MIN_VALUE:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324),相应的,最接近0的负数为-Number.MIN_VALUE。 Number.MAX_SAFE_INTEGER:表示能够精确表示的最大整数,即9007199254740991。 Number.MIN_SAFE_INTEGER:表示能够精确表示的最小整数,即-9007199254740991。 ``` **(4)Number对象实例的方法** ``` toString() //用来将一个数值转为字符串形式.可以接受一个参数,表示输出的进制。如果省略这个参数,默认将数值先转为十进制,再输出字符串;否则,就根据参数指定的进制,将一个数字转化成某个进制的字符串。 toFixed() //用于将一个数转为指定位数的小数,返回这个小数对应的字符串。 toExponential() //用于将一个数转为科学计数法形式。可传入一个参数,参数表示小数点后有效数字的位数,范围为0到20,超出这个范围,会抛出一个RangeError。 toPrecision() //用于将一个数转为指定位数的有效数字。 ``` **3.4 String 对象** **(1)生成实例对象** ``` var s = new String() ``` **(2)String对象的属性** ``` s.length //返回字符串的长度 ``` **(3)方法** ``` s.chatAt(index) //返回指定位置的字符 s.fromCharCode() //该方法的参数是一系列Unicode码点,返回对应的字符串。 s.charCodeAt(index) //返回给定位置字符的Unicode码点(十进制表示) s.concat(s2) //用于连接两个字符串 s.slice(start,end) //用于从原字符串取出子字符串并返回,不改变原字符串。第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。 s.substring(start,end) //用于从原字符串取出子字符串并返回,不改变原字符串.第一个参数表示子字符串的开始位置,第二个位置表示结束位置。 s.substr(start,length) //用于从原字符串取出子字符串并返回,不改变原字符串。第一个参数是子字符串的开始位置,第二个参数是子字符串的长度。如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。 s.indexOf(s) //返回给定元素在字符串中第一次出现的位置,如果没有出现则返回-1。可以接受第二个参数,表示搜索的开始位置 s.lastIndexOf() //返回给定元素在字符串中最后一次出现的位置,如果没有出现则返回-1。 s.trim() //用于去除字符串两端的空格,返回一个新字符串 s.toLowerCase() //用于将一个字符串全部转为小写,返回一个新字符串,不改变原字符串。 s.toUpperCase() //全部转为大写 s.localeCompare(s2) //用于比较两个字符串。它返回一个整数,如果小于0,表示第一个字符串小于第二个字符串;如果等于0,表示两者相等;如果大于0,表示第一个字符串大于第二个字符串。 s.match(regexp) //用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。 s.search() //返回值为匹配的第一个位置。如果没有找到匹配,则返回-1。 s.replace(oldValue,newValue) //用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。 s.split() //按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。还可传入第二个参数,决定了返回数组的成员数。 ``` **3.5 Math对象** **(1)属性** ``` Math.E:常数e。 Math.LN2:2的自然对数。 Math.LN10:10的自然对数。 Math.LOG2E:以2为底的e的对数。 Math.LOG10E:以10为底的e的对数。 Math.PI:常数Pi。 Math.SQRT1_2:0.5的平方根。 Math.SQRT2:2的平方根。 ``` **(2)数学方法** ``` Math.abs():返回参数的绝对值 Math.ceil():向上取整,接受一个参数,返回大于该参数的最小整数。 Math.floor():向下取整 Math.max(n,n1,...):可接受多个参数,返回最大值 Math.min(n,n1,..):可接受多个参数,返回最小值 Math.pow(n,e):指数运算, 返回以第一个参数为底数、第二个参数为幂的指数值。 Math.sqrt():返回参数值的平方根。如果参数是一个负值,则返回NaN。 Math.log():返回以e为底的自然对数值。 Math.exp():返回e的指数,也就是常数e的参数次方。 Math.round():四舍五入 Math.random():返回0到1之间的一个伪随机数,可能等于0,但是一定小于1。 ``` **(3)三角函数方法** ``` Math.sin():返回参数的正弦 Math.cos():返回参数的余弦 Math.tan():返回参数的正切 Math.asin():返回参数的反正弦(弧度值) Math.acos():返回参数的反余弦(弧度值) Math.atan():返回参数的反正切(弧度值) ``` **3.6 JSON对象** **(1)方法** ``` JSON.stringify() //用于将一个值转为字符串。该字符串应该符合JSON格式,并且可以被JSON.parse方法还原。 //(JSON.stringify(obj, selectedProperties))还可以接受一个数组,作为第二个参数,指定需要转成字符串的属性。 //还可以接受第三个参数,用于增加返回的JSON字符串的可读性。如果是数字,表示每个属性前面添加的空格(最多不超过10个);如果是字符串(不超过10个字符),则该字符串会添加在每行前面。 JSON.parse() //用于将JSON字符串转化成对象。 ``` **3.7 console对象** **(1)方法** ``` console.log(text,text2,...) //用于在console窗口输出信息。它可以接受多个参数,将它们的结果连接起来输出。如果第一个参数是格式字符串(使用了格式占位符),console.log方法将依次用后面的参数替换占位符,然后再进行输出。 console.info() //在console窗口输出信息,同时,会在输出信息的前面,加上一个蓝色图标。 console.debug() //在console窗口输出信息,同时,会在输出信息的前面,加上一个蓝色图标。 console.warn() //输出信息时,在最前面加一个黄色三角,表示警告; console.error() //输出信息时,在最前面加一个红色的叉,表示出错,同时会显示错误发生的堆栈 console.table() //可以将复合类型的数据转为表格显示。 console.count() //用于计数,输出它被调用了多少次。 console.dir() //用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。 console.dirxml() //用于以目录树的形式,显示DOM节点。 console.assert() //接受两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为false,才会输出第二个参数,否则不会有任何结果。 //这两个方法用于计时,可以算出一个操作所花费的准确时间。 console.time() console.timeEnd() //time方法表示计时开始,timeEnd方法表示计时结束。它们的参数是计时器的名称。调用timeEnd方法之后,console窗口会显示“计时器名称: 所耗费的时间”。 console.profile() //用来新建一个性能测试器(profile),它的参数是性能测试器的名字。 console.profileEnd() //用来结束正在运行的性能测试器。 console.group() console.groupend() //上面这两个方法用于将显示的信息分组。它只在输出大量信息时有用,分在一组的信息,可以用鼠标折叠/展开。 console.groupCollapsed() //用于将显示的信息分组,该组的内容,在第一次显示时是收起的(collapsed),而不是展开的。 console.trace() //显示当前执行的代码在堆栈中的调用路径。 console.clear() //用于清除当前控制台的所有输出,将光标回置到第一行。 ``` ';

作用域

最后更新于:2022-04-01 23:54:58

## 作用域 **1.1 作用域** 几乎所有的编程语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。 作用域有全局作用域和局部作用域(一般是在函数内)之分。 **1.1.1 全局作用域** 在代码中任何地方都能访问到的对象拥有全局作用域。 一般来说,拥有全局作用域有以下几种情况: **(1)在最外层的函数和在最外层函数外面定义的变量拥有全局作用域** 例子: ``` var name = 'tg'; function test(){ var name2 = 'tg'; } ``` 在上面的例子中,变量name和函数test()就拥有全局作用域 **(2)所有未定义而直接赋值(不用var关键字声明)的变量被自动声明为拥有全局作用域** ``` funciton test(){ var age = 10; name = 'tg'; } test(); console.log(age); // 会报错undefined console.log(name); // "tg" ``` 变量name拥有全局作用域,而age在函数外面是无法访问到的 **(3)所有window对象的属性拥有全局作用域** window对象的内置属性都由拥有全局作用域,比如window.location、Date对象等 **1.1.2 局部作用域** 局部作用域不像全局作用域,它被限定在一个范围内,最常见的局部作用域就是在函数内部,我们也称为**函数作用域**。 **函数作用域**是指变量能够被使用的代码区间。超出作用域的变量值一般为undefined,或者被其他同名变量值所覆盖。 ``` funciton test(){ var age = 10; console.log(age); } test(); // 10 console.log(age); // 会报错undefined ``` 在上面的例子中,在函数外面是无法访问到变量age的,但在函数内部是可以访问的。 要记住,对于变量或函数,它的作用域取决于定义时的作用域,而不是在调用它的作用域中。 **1.2 作用域链** 在ES 5中,将作用域链称为**词法环境**。 当代码在一个作用域中执行时,会创建变量对象的一个作用域链(scope chain)。 作用域链的用途:保证对执行环境有权访问的所有变量和函数的有序访问。 作用域链的前端,始终都是当前执行的代码所在作用域的变量对象。如果这个环境是函数,则将其活动对象作为变量对象,然后对于每一个函数的形参,都命名为该活动对象的命名属性。 活动对象在最开始只包含一个变量,即arguments对象(在全局环境中是不存在的)。 看一个例子: ``` var name = 'p'; function test(){ var name = 'tg'; function get(){ console.log(name); } get(); } test(); // "tg" ``` 当执行get()时,将创建函数get()的执行环境(调用对象),并将该对象置于作用域链的前端(开头),然后将函数test()的调用对象链接在之后,最后是全局对象,然后从作用域链的前端开始查找标识符name,很显然,变量name的值是"tg"; 作用域链:get() -> test() -> window 每次进入一个新的作用域,都会创建一个用于搜索变量和函数的作用域链。 函数的局部变量不仅有权访问函数作用域中的变量,而且有权访问其他包含(父)环境,乃至全局作用域。但是全局作用域只能访问在全局作用域中定义的变量和函数,不能直接访问局部作用域中的任何数据。 变量的作用域有助于确定应该何时释放内存。 **1.3 JavaScript没有块级作用域** JavaScript中并没有块级作用域。也就是说,对于if、for、while、switch等块结构是没有作用域的。 ``` if(true){ var name = 'tg'; } console.log(name); // "tg" ``` 在if语句里定义了一个name变量,但它并不会向在函数内那样,但函数执行结束后就销毁,而是会一直存在,因为它被添加到了当前的执行环境(也就是全局环境)中。 对于for循环也是一样: ``` for(var i = 0; i < 10; i++){ //循环体 } console.log(i); // 10 ``` **(1)声明变量** 使用var声明的变量会自动被添加到最接近的环境中,比如在函数内部,最接近的环境就是函数的局部环境。如果初始化变量没有使用var声明,会自动被添加到全局环境中。 **(2)查询标识符** 标识符的查询规则是:逐级向上查询,如果在局部环境中找到了该标识符,搜索过程就停止,变量就绪,否则,会继续向上查询,直到全局环境的变量对象,如果在全局环境中也没有找到这个标识符,就表示该变量尚未声明(通常会报错)。 ``` var name = 'tg2'; function test(){ var name = 'tg'; console.log(name); // "tg" } test(); ``` 在上面的例子中,在函数内部已经找到了name标识符,所以返回的是"tg"
';

原型链

最后更新于:2022-04-01 23:54:56

## 原型链 **3.1 原型** 每一个JavaScript对象(null除外)都和另一个对象相关联,也可以说,继承另一个对象。另一个对象就是我们熟知的“原型”(`prototype`),每一个对象都从原型继承属性。只有null除外,它没有自己的原型对象。 我们可以通过`__proto__`(首尾都是双下划线)来获取实例的原型对象。 注意:`__proto__`连接的是实例与构造函数的原型对象之间,而不是实例与构造函数之间。 所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码`Object.prototype`获得对原型对象的引用。 通过关键字new和构造函数调用创建的对象的原型就是构造函数的`prototype`属性的值。比如:通过new Object()创建的对象继承自Object.prototype;通过new Array()创建的对象的原型就是Array.prototype。 没有原型的对象为数不多,`Object.prototype`就是其中之一,它不继承任何属性。 所有的内置构造函数都具有一个继承自`Object.prototype`的原型。 **3.1 原型链** 在JavaScript中,原型链是实现继承的主要方式。 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。 可用`__proto__`属性来获取或设置对象的原型。 每个构造函数都有一个原型对象(prototype),原型对象本身也是对象,所以它也有自己的原型,而它本身的原型对象也有自己的原型,这样层层递进,就形成了一条链,这个链就是**原型链**。 JavaScript引擎在访问对象的属性时,会先在对象本身中查找,如果没有找到,则会去原型链中查找,如果找到,则返回值,如果整个原型链中都没有找到这个属性,则返回undefined。 ``` var person = { name: 'human' }; var person1 = { name: 'tg', __proto__: person }; var person2 = { __proto__: person }; console.log(person1.name); // "tg" console.log(person2.name); // "human" console.log(person1.id); // undefined ``` 从上面例子的运行结果,我们也可以看出原型链的运行机制:从对象本身出发,沿着`__proto__`查找,直到找到属性名称相同的值(没有找到,则返回undefined)。 所有对象都继承自`Ojbect`,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例,因此默认的原型都会包含一个内部指针,指向`Object.prototype`。而`Object.prototype`的`__proto__`的属性值为null,标志着原型链的结束。 **3.2 原型和实例** 有两种方式来确定原型和实例之间的关系: - 使用`instanceof`操作符 ``` function Person(){} var person = new Person(); console.log(person instanceof Object); // true console.log(person instanceof Person); // true ``` - 使用`isPrototypeOf()`方法。 ``` console.log(Object.prototype.isPrototypeOf(person)); // true console.log(Person.prototype.isPrototypeOf(person)); // true ```
';

this关键字

最后更新于:2022-04-01 23:54:54

## this关键字 JavaScript代码都存在于一定的`上下文对象`中。上下文对象通过`this`关键字来动态指定,它永远指向当前对象。简单的说,就是返回属性或方法“当前”所在的对象。 **this的工作原理** 在5种不同的情况下,`this`指向的各不相同。 **(1)全局范围内** ``` this ``` 当在全局范围内使用`this`,它将指向全局对象 **(2)函数调用** ``` function test(){ console.log(this); } test(); ``` 这里的`this`也指向全局对象。 **(3)方法调用** ``` test.foo(); ``` 这个例子中,`this`指向test对象。 **(4)调用构造函数** ``` new test(); ``` 如果函数倾向于`new`关键词一块使用,则我们称这个函数是构造函数。在函数内部,`this`指向新创建的实例对象。 **(5)显式的设置this** ``` function test(a, b) {} var bar = {}; test.apply(bar, [1, 2]); //数组将会会被扩展 test.call(bar , 1, 2); // 传递到test的参数是: a = 1, b = 2 ``` 当使用`Function.prototype`上的`call`或`apply`方法时,函数内的`this`将会被显式设置为函数调用的第一个参数。 **改变this指向的方法** JavaScript提供了call、apply、bind这三个方法,来切换/固定this的指向。 **(1)call()** 语法: ``` call([thisObj[,arg1[, arg2[, [,.argN]]]]]) ``` 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 **(2)apply()** 语法: ``` apply([thisObj[,argArray]]) ``` 定义:应用某一对象的一个方法,用另一个对象替换当前对象。 说明: 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。 bind()方法 bind()方法是在ECMAScript 5中新增的方法。 toString()方法 函数的toString方法返回函数的源码。 ``` function f(){ return 1; } f.toString() //function f(){ // return 1; //} ``` **(3)bind()** bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。 ``` var bar=function(){ console.log(this.x); } var foo={ x:3 } bar(); bar.bind(foo)(); /*或*/ var func=bar.bind(foo); func(); 输出: undefined 3 ``` 注意:bind()返回的是函数。
';

概述

最后更新于:2022-04-01 23:54:52

## 对象概述 面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript中并没有类的概念,所以它的对象也有有所不同。 ECMAScript对象是一个无序属性的集合,其属性可以包含基本值、对象或函数。 对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。 每个对象都是基于一个引用类型创建的。 **1、对象** **1.1 创建对象** (1)创建自定义对象的最简单方式就是创建一个Object的实例,然后给其添加属性和方法: ``` var person = new Object(); person.name = 'tg'; person.age = 10; person.say = function(){ console.log(this.name); } ``` 上面的例子创建了一个名为person的对象,并为它添加了两个属性(name、age)和一个方法(say())。 (2)对象字面量 ``` var person = { name: 'tg', age: 10, say: function(){ console.log(this.name); } } ``` 这个person对象和上面例子是等价的。 **1.2 属性类型** ECMA-262第5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征。ECMA-262定义这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问它们。该规范将它们放在了两对方括号中,表示特性是内部值,如[[Enumerable]]。 ECMAScript中有两种属性:数据属性和访问权属性 **1.2.1 数据属性** 数据属性包含一个数据值的位置,在这个位置可以读取和写入值。 数据属性有4个描述特性: - [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。 - [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。 - [[Writable]]:表示能否修改属性的值。 - [[Value]]: 包含这个属性的数据值。读取属性值时,从这个位置读;写入属性值时,把新值保存在这个位置。默认值为undefined。 要修改属性默认的特性,必须使用ECMAScript 5的`Object.defineProperty()`方法,这个方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable和value。 ``` var person = {}; Object.defineProperty(person, 'name', { writable: false, value: 'tg' }); console.log(person.name); // "tg" person.name = 'tg2'; console.log(person.name); // "tg" ``` 在上面的例子中,我们将person对象中的名为name的属性的`writable`设置为false,也就是不可修改,所以即使后面执行了person.name='tg2',最后person对象的name值依旧是原始值。 注意:在严格模式下,如果对一个不可修改的属性执行赋值操作,会抛出错误;非严格模式下则忽略赋值操作。 一旦将configurable特性设置为false后,就不能再把它变回可配置的了,如果再修改除writable之外的特性,都会导致错误。 **1.2.2 访问器属性** 访问器属性不包含数据值,它们包含一对getter和setter函数(非必需)。在读取访问器属性时,会调用getter函数,返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,它负责决定如何处理数据。 访问器属性: - [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。 - [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。 - [[Get]]:在读取属性时调用的函数,默认为undefined - [[Set]]:在写入属性时调用的函数,默认为undefined 访问器属性不能直接定义,也是要使用`Object.defineProperty()`方法来定义。 ``` var person = { _age: 20, intro: '' }; Object.defineProperty(person, 'age', { get: function() { return this._age; }, set: function(newValue){ if(newValue < 18) { this.intro = '装嫩'; this._age = newValue; } } }); console.log(person.age); // 20 person.age = 17; console.log(person.intro); // "装嫩" ``` 在上面的例子中,访问器属性age有一个getter函数和一个setter函数。getter函数返回`_age`的值,setter函数通过判断`age`的设置值来改变其他属性值。 **1.2.3 定义多个属性** ECMAScript 5提供的`Object.defineProperties()`方法可以通过描述符一次定义多个属性,这个方法接收两个对象参数,第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象要添加或修改的属性一一对应。 ``` var person = {}; Object.defineProperties(person, { _age: { value: 20 }, intro: { value: '' }, age: { get: function(){ return this._age; }, set: function(newValue){ if(newValue < 18) { this.intro = '装嫩'; this._age = newValue; } } } }); ``` **1.2.4 读取属性的特性** ECMAScript 5提供的`Object.getOwnPropertyDescriptor()`方法可以取得给定属性的描述符,它接受两个参数:属性所在的对象和要读取其描述符的属性名称,返回来的是一个对象,如果是访问器属性,这个对象的属性有configurable、enumerable、get和set;如果是数据属性,这个对象的属性有configurable、enumerable、writable和value。 ``` var person = { _age: 20, intro: '' }; Object.defineProperty(person, 'age', { get: function() { return this._age; }, set: function(newValue){ if(newValue < 18) { this.intro = '装嫩'; this._age = newValue; } } }); var descriptor = Object.getOwnPropertyDescriptor(person,'age'); console.log(descriptor.enumerable); // false console.log(typeof descriptor.get); // "function" ``` 在JavaScript中,可以针对任何对象--包括DOM和BOM对象,使用`Object.getOwnPropertyDescriptor()`方法。
';

面向对象的程序设计

最后更新于:2022-04-01 23:54:50

## 面向对象的程序设计
';

Notification

最后更新于:2022-04-01 23:54:47

## Notification Notifications API 的通知接口用于向用户配置和显示桌面通知。 语法: ``` let notification = new Notification(title, options) ``` 参数: * title:一定会被显示的通知标题 * options 可选,一个被允许用来设置通知的对象。它包含以下属性: - dir : 文字的方向;它的值可以是 auto(自动), ltr(从左到右), or rtl(从右到左) - lang: 指定通知中所使用的语言。这个字符串必须在 BCP 47 language tag 文档中是有效的。 - body: 通知中额外显示的字符串 - tag: 赋予通知一个ID,以便在必要的时候对通知进行刷新、替换或移除。 - icon: 一个图片的URL,将被用于显示通知的图标。 ### 属性 **静态属性** `Notification.permission ` 只读,一个用于表明当前通知显示授权状态的字符串。可能的值包括:denied (用户拒绝了通知的显示), granted (用户允许了通知的显示), 或 default (因为不知道用户的选择,所以浏览器的行为与 denied 时相同). **实例属性** | 属性 | 描述 | | :--: | :--: | | Notification.title | 在构造方法中指定的 title 参数 | | Notification.dir | 通知的文本显示方向 | | Notification.lang | 通知的语言 | | Notification.body | 通知的文本内容 | | Notification.tag | 通知的 ID | | Notification.icon | 通知的图标图片的 URL 地址 | **事件** | 事件 | 描述 | | :--: | :--: | | Notification.onclick | 处理 click 事件的处理 | | Notification.onshow | 处理 show 事件的处理 | | Notification.onerror | 处理 error 事件的处理 | | Notification.onclose | 处理 close 事件的处理 | ### 方法 **静态方法** `Notification.requestPermission()` 用于当前页面想用户申请显示通知的权限。这个方法只能被用户行为调用(比如:onclick 事件),并且不能被其他的方式调用。 **实例方法** | 方法 | 描述 | | :--: | :--: | | Notification.close() | 用于关闭通知 | **简单实例** ``` // 申请权限 function requestNotification(title, options) { // 先检查浏览器是否支持 if (!('Notification' in window)) { alert('This browser does not support desktop notification'); } // 检查用户是否同意接受通知 else if (Notification['permission'] === 'granted') { this.openNotification(title, options); } // 否则我们需要向用户获取权限 else if (Notification['permission'] !== 'denied') { Notification.requestPermission((permission) => { if (permission === 'granted') { // 如果用户同意,就可以向他们发送通知 openNotification(title, options); } }); } } function openNotification(title, options) { const notification = new Notification(title, options); notification.onclose = (event) => { // 当关闭时 } } requestNotification('您有一条消息通知', { body: '来自XX', requireInteraction: true, data: {}, icon: 'notification-icon.jpg' }); ```
';

Web Speech

最后更新于:2022-04-01 23:54:45

## Web Speech 语音输入 老版本中,如果我们要部署一个带有语音搜索功能的input,可用如下代码: ``` ``` 然后通过webkitspeechchange事件来监听用户输入: ``` var speech = document.getElementById('speech'); speech.onwebkitspeechchange = funciton(){ } ``` 注意:目前只有Chrome支持这种带语音的输入框。 在新版本中,我们还可以用JavaScript操作语音输入,就是通过Web Speech这个API。(也是只有Chrome支持) 主要有两部分: - 语言识别(将所说的转换成文本文字) - 语言合成(将文本文字读出来) **1、语言识别** **1.1 SpeechRecognition对象** 这个API部署在`SpeechRecognition`对象之上。 **1.1.1 检测是否支持** ``` if ('webkitSpeechRecognition' in window) { // 支持 } ``` 确定支持后,新建一个`SpeedchRecognition`的实例对象: ``` if ('webkitSpeechRecognition' in window) { var recognition = new webkitSpeechRecognition(); } ``` **1.1.2 属性和方法** **属性** - continous:是否让浏览器始终进行语言识别,默认为false,也就是说,当用户停止说话时,语音识别就停止了。这种模式适合处理短输入的字段。 - maxAlternatives:设置返回的最大语音匹配结果数量,默认为1 - lang:设置语言类型,默认值就继承自HTML文档的根节点或者是祖先节点的语言设置。 **方法** - start():启动语音识别 - stop():停止语音识别 - abort():中止语音识别 **1.1.3 事件** 浏览器会询问用户是否许可浏览器获取麦克风数据 这个API提供了11个事件。 - audiostart:当开始获取音频时触发,也就是用户允许时。 - audioend:当获取音频结束时触发 - error:当发生错误时触发 - nomatch:当找不到与语音匹配的值时触发 - result: 当得到与语音匹配的值时触发,它传入的是一个SpeechRecognitionEvent对象,它的results属性就是语音匹配的结果数组,最匹配的结果排在第一位。该数组的每一个成员是SpeechRecognitionResult对象,该对象的transcript属性就是实际匹配的文本,confidence属性是可信度(在0到1之间) - soundstart - soundend - speechstart - speechend - start:当开始识别语言时触发 - end:当语音识别断开时触发 看个实例: ``` var speech = document.getElementById('speech'); if('webkitSpeechRecognition' in window) { var recognition = new webkitSpeechRecognition(); recognition.onaudiostart = function(){ speech.value = '开始录音'; }; recognition.ononmatch = function(){ speech.value = '没有匹配结果,请再次尝试'; }; recognition.onerror = function(){ speech.value ='错误,请再次尝试'; }; // 如果得到与语音匹配的值,则会触发result事件。 recognition.onresult = function(event){ if(event.results.length > 0) { var results = event.results[0]; var topResult = results[0]; if(topResult.confidence > 0.5) { } else { speech.value = '请再次尝试'; } } } } ``` **2、语音合成** 语音合成只有Chrome和Safari支持。 **2.1 SpeechSynthesisUtterance对象** 打开控制台,黏贴下面的函数,然后调用: ``` funciton speak(textToSpeak){ var newUtterance = new SpeechSynthesisUtterance(); newUtterance.text = textToSpeak; window.speechSynthsisi.speak(newUtterance); } ``` **2.1 SpeechSynthesisUtteranc的实例对象的属性** - text:识别的文本 - volume:音量(0~1) - rate:发音速度 - pitch:音调 - voice:声音 - lang:语言类型 **2.2 window.speechSynthesis.getVoices()** 通过API提供给用户的声音在很大程度上取决于操作系统。谷歌有自己的一套给Chrome的默认声音,可以在Mac OS X,Windows和Ubuntu上使用。Mac OS X的声音也可用,所以和OSX的Safari的声音一样。你可以通过开发者工具的控制台看有哪种声音可用。 `window.speechSynthesis.getVoices()`用来获取发音列表,返回一个数组,每个元素的name属性表示声音名称 **2.3 window.speechSynthsisi.speak()** `window.speechSynthsisi.speak()`方法是用于发音的。
';

Performance API

最后更新于:2022-04-01 23:54:43

## Performance API 高精度时间戳 PerFormance API是ECMAScript 5才引入的,它的精度可达到1毫秒的千分之一。 目前,所有主要浏览器都已经支持`performance`对象,包括Chrome 20+、Firefox 15+、IE 10+、Opera 15+。 **1.1 performance.timing对象** `performance`对象是全局的,它的`timing`属性是一个对象,它包含了各种与浏览器性能有关的时间数据,提供浏览器处理网页各个阶段的耗时。 `performance.timing`对象包含下列属性(全部只读): ``` navigationStart:当前浏览器窗口的前一个网页关闭,发生unload事件时的Unix毫秒时间戳。如果没有前一个网页,则等于fetchStart属性。 unloadEventStart:如果前一个网页与当前网页属于同一个域名,则返回前一个网页的unload事件发生时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。 unloadEventEnd:如果前一个网页与当前网页属于同一个域名,则返回前一个网页unload事件的回调函数结束时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。 redirectStart:返回第一个HTTP跳转开始时的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。 redirectEnd:返回最后一个HTTP跳转结束时(即跳转回应的最后一个字节接受完成时)的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。 fetchStart:返回浏览器准备使用HTTP请求读取文档时的Unix毫秒时间戳。该事件在网页查询本地缓存之前发生。 domainLookupStart:返回域名查询开始时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。 domainLookupEnd:返回域名查询结束时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。 connectStart:返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值。 connectEnd:返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。 secureConnectionStart:返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。 requestStart:返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。 responseStart:返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。 responseEnd:返回浏览器从服务器收到(或从本地缓存读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。 domLoading:返回当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的readystatechange事件触发时)的Unix毫秒时间戳。 domInteractive:返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的Unix毫秒时间戳。 domContentLoadedEventStart:返回当前网页DOMContentLoaded事件发生时(即DOM结构解析完毕、所有脚本开始运行时)的Unix毫秒时间戳。 domContentLoadedEventEnd:返回当前网页所有需要执行的脚本执行完成时的Unix毫秒时间戳。 domComplete:返回当前网页DOM结构生成时(即Document.readyState属性变为“complete”,以及相应的readystatechange事件发生时)的Unix毫秒时间戳。 loadEventStart:返回当前网页load事件的回调函数开始时的Unix毫秒时间戳。如果该事件还没有发生,返回0。 loadEventEnd:返回当前网页load事件的回调函数运行结束时的Unix毫秒时间戳。如果该事件还没有发生,返回0。 ``` **1.2 performance中的方法** **(1)performance.now()** `performance.now`方法返回当前网页自从`performance.timing.navigationStart`到当前时间之间的微秒数(毫秒的千分之一)。也就是说,它的精度可以达到100万分之一秒。 **(2)performance.mark()** mark方法用于为相应的视点做标记。 clearMarks方法用于清除标记,如果不加参数,就表示清除所有标记。 **(3)performance.getEntries()** 浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等等)发出一个HTTP请求。`performance.getEntries`方法以数组形式,返回这些请求的时间统计信息,有多少个请求,返回数组就会有多少个成员。 **1.3 performance.navigation对象** 除了时间信息,performance还可以提供一些用户行为信息,主要都存放在performance.navigation对象上面。 它有两个属性: **(1)performance.navigation.type** 该属性返回一个整数值,表示网页的加载来源,可能有以下4种情况: ``` 0:网页通过点击链接、地址栏输入、表单提交、脚本操作等方式加载,相当于常数performance.navigation.TYPE_NAVIGATENEXT。 1:网页通过“重新加载”按钮或者location.reload()方法加载,相当于常数performance.navigation.TYPE_RELOAD。 2:网页通过“前进”或“后退”按钮加载,相当于常数performance.navigation.TYPE_BACK_FORWARD。 255:任何其他来源的加载,相当于常数performance.navigation.TYPE_UNDEFINED。 ``` **(2)performance.navigation.redirectCount** 该属性表示当前网页经过了多少次重定向跳转。
';

Page Visibility API

最后更新于:2022-04-01 23:54:40

## PageVisibility **1、PageVibility** PageVisibility API是用于判断页面是否处于浏览器的当前窗口,即是否可见。 这API是部署在`document`对象上的。 **1.1 属性** 它有两个属性: - `document.hidden`:返回一个布尔值,表示当前是否被隐藏,只读 - `document.visibilityState`:只读,表示页面当前的状态,有四个可能值:`visibile`(页面可见)、`hidden`(页面不可见)、`prerender`(页面正处于渲染之中,不可见)、`unloaded`(如果文档被卸载了) 在使用这两个属性时,要加上不同浏览器的私有前缀: 获取`hidden`属性值: ``` function getHiddenProp() { var prefixes = ['webkit', 'moz', 'ms', 'o']; if ( 'hidden' in document) return 'hidden; for(var i = 0; i < prefixes.length; i++) { var hidden = prefixes[i] + 'Hidden'; if( hidden in document) { return hidden; } }; return null; } ``` 获取`visibilityState`属性 ``` function getVisibilityState() { var prefixes = ['webkit', 'moz', 'ms', 'o']; if ( 'visibilityState' in document) return 'visibilityState; for(var i = 0; i < prefixes.length; i++) { var visibilityState = prefixes[i] + 'VisibilityState'; if( hidden in document) { return visibilityState; } }; return null; } ``` **1.2 事件** 当页面的可见状态发生变化时,会触发`visibilityChange`事件(也是需要加上私有前缀) ``` var hidden = getHiddenProp(); var visibilityChange = hidden.split(/[H|h]/, '')[0] + 'visibilitychange'; document.addEventListener(visibilityChange, function(){ console.log( document[getVisibilityState] ); }); ```
';

WebRTC

最后更新于:2022-04-01 23:54:38

## WebRTC WebRTC(Web Real-Time Communication,网页实时通信),是一个支持网页浏览器进行实时语音对话或视频对话的API。 **1、getUserMedia** 要播放摄像头的影像,首先需要一个video标签: ``` ``` 获取摄像头影像主要是通过`navigator.getUserMedia`这个接口,这个接口的支持情况已经逐渐变好了([点击这里](http://caniuse.com/#search=getUserMedia)),不过,使用的时候还是要加上前缀的。 兼容代码: ``` navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; ``` 语法: ``` navigator.getUserMedia(constraints, successCallback, errorCallback); ``` 参数说明: - constraints:Object类型,指定了请求使用媒体的类型 - succeCallback:启用成功时的函数,它传入一个参数,为视频流对象,可以进一步通过`window.URL.createObjectURL()`接口把视频流转换为对象URL。 - errorCallback:启动失败时的函数。它传入一个参数,为错误对象(chrome)或错误信息字符串(Firefox),可能值: ``` PERMISSION_DENIED:用户拒绝提供信息。 NOT_SUPPORTED_ERROR:浏览器不支持硬件设备。 MANDATORY_UNSATISFIED_ERROR:无法发现指定的硬件设备。 ``` 例如要启用视频设备(摄像头),可这样: ``` navigator.getUserMedia({ video: true }); ``` 如果要同时启用视频设备和音频设备,可这样: ``` navigator.getUserMedia({ video: true, audio: true }); ``` **1.1 获取摄像头完整实例** ``` ``` 当点击直播按钮时,电脑会提升用户是否允许使用摄像头,允许之后,网页上就可以实时显示摄像头影像了。如果不允许,就会触发错误事件。 **1.1.1 截图** 除了实时直播外,我们还可以做实时截图效果,这时我们需要利用``元素来画图,代码如下: ```
``` **1.1.2 保存图片** 当然,截图后,你也可以保存下来: ``` 下载图片 var url = canvas.toDataURL('image/png'); document.getElementById('download').src = url; ``` **1.2 捕获麦克风声音** 要通过浏览器捕获声音,需要借助Web Audio API。 ``` window.AudioContext = window.AudioContext || window.webkitAudioContext; var context = new AudioContext(); function onSuccess(stream){ var audioInput = context.createMediaStreamSource(stream); audioInput.connect(context.destination); } navigator.getUserMedia({audio: true} ,onSuccess); ```
';

Luminosity API

最后更新于:2022-04-01 23:54:36

## Luminosity **6、屏幕亮度(Luminosity API)** Luminosity API用来屏幕亮度调节,不过目前只有Firefox支持。 当移动设备的亮度传感器感知外部亮度发生显著变化时,会触发devicelight事件。 ``` window.addEventListener('devicelight', function(event) { console.log(event.value + 'lux'); }); ``` 上面代码表示,devicelight事件的回调函数,接受一个事件对象作为参数。该对象的value属性就是亮度的流明值。
';

vibrate

最后更新于:2022-04-01 23:54:34

## vibrate **5、设备震动(Vibration API)** Vibration接口用于在浏览器中发出命令,使得设备振动。 **(1)检测是否可用** 目前,只有Chrome和Firefox的Android平台最新版本支持它。 ``` navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; if (navigator.vibrate) { // 支持 } ``` **(2)振动** ``` navigator.vibrate(1000); ``` vibrate()方法的参数就是振动持续的毫秒数,除了单个数值外,还可以接受一个数组作为参数,表示振动的模式。偶数位置的数组成员表示振动的毫秒数,奇数位置的数组成员表示等待的毫秒数。 ``` navigator.vibrate([200,100,300]) ``` 上面代码表示,设备先振动200毫秒,然后等待100毫秒,再接着振动300毫秒。 注意:vibrate是一个非阻塞式的操作,即手机振动的同时,JavaScript代码仍然继续向下运行。要停止振动,只有将0毫秒或者一个空数组传入vibrate方法。
';

Blob

最后更新于:2022-04-01 23:54:31

## Blob **2、Blob** Blob(Binary Large Object)对象代表了一段二进制数据,提供了一系列操作接口。比如通过new Blob()创建的对象就是Blob对象.又比如,在XMLHttpRequest里,如果指定responseType为blob,那么得到的返回值也是一个blob对象. **2.1 生成Blob对象** 生成Blob对象有两种方法:一种是使用Blob构造函数,另一种是对已有的Blob对象使用slice()方法切出一段。 **(1)Blob构造函数** ``` var blob = new Blob(data, type) ``` Blob构造函数接受两个参数: 参数data是一组数据,所以必须是数组,即使只有一个字符串也必须用数组装起来. 参数type是对这一Blob对象的配置属性,目前也只有一个type也就是相关的MIME需要设置 type的值: 'text/csv,charset=UTF-8' 设置为csv格式,并设置编码为UTF-8 'text/html' 设置成html格式 注意:任何浏览器支持的类型都可以这么用 ``` var blob = new Blob(['我是Blob'],{type: 'text/html'}); ``` **2.2 属性** ``` blob.size //Blob大小(以字节为单位) blob.type //Blob的MIME类型,如果是未知,则是“ ”(空字符串) ``` **2.3 slice()** slice()返回一个新的Blob对象,包含了源Blob对象中指定范围内的数据。 ``` blob.slice( optional long long start, optional long long end, optional DOMString contentType }; ``` 参数说明: start 可选,开始索引,可以为负数,语法类似于数组的slice方法.默认值为0. end 可选,结束索引,可以为负数,语法类似于数组的slice方法.默认值为最后一个索引. contentType可选 ,新的Blob对象的MIME类型,这个值将会成为新的Blob对象的type属性的值,默认为一个空字符串. **2.4 Blob的使用** 使用Blob最简单的方法就是创建一个URL来指向Blob: ``` 下载 var data= 'Hello world!'; var blob = new Blob([data], { type: 'text/html,charset=UTF-8' }); window.URL = window.URL || window.webkitURL; document.querySelector("#getData").href = URL.createObjectURL(blob); ``` 上面的代码将Blob URL赋值给a,点击后提示下载文本文件data.txt,文件内容为“Hello World”。 **2.5 URL.createObjectURL()** ``` objectURL = URL.createObjectURL(blob); ``` 使用URL.createObjectURL()函数可以创建一个Blob URL,参数blob是用来创建URL的File对象或者Blob对象,返回值格式是:blob://URL。 注意:在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法传入创建的URL为参数,用来释放它。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。 **2.6 乱码问题** 当数据中包含汉字时,导出的文件可能会出现乱码,不过我们可以这样解决: ``` var data = "\ufeff" + "汉字"; ```
';

检测设备方向

最后更新于:2022-04-01 23:54:29

## 检测设备方向 **7、手机设备方向** **7.1 方向** Orientation API用于检测手机的摆放方向(竖放或横放)。 **(1)检测浏览器是否支持** ``` if(window.DeviceOrientationEvent){ //支持 }else{ //不支持 } ``` **(2)监听方向变化** 一旦设备的方向发生变化,会触发deviceorientation事件,可以对该事件指定回调函数。 ``` window.addEventListener("deviceorientation", listener,false); function listener(event){ var alpha = event.alpha; var beta = event.beta; var gamma = event.gamma; } ``` 上面代码中,event事件对象有alpha、beta和gamma三个属性,它们分别对应手机摆放的三维倾角变化。要理解它们,就要理解手机的方向模型。当手机水平摆放时,使用三个轴标示它的空间位置:x轴代表横轴、y轴代表竖轴、z轴代表垂直轴。event对象的三个属性就对应这三根轴的旋转角度。 - alpha:表示围绕z轴的旋转,0~360(度)。当设备水平摆放时,顶部指向地球的北极,alpha此时为0。 - beta:表示围绕x轴的旋转,-180~180(度),由前向后。当设备水平摆放时,beta此时为0。 - gramma:表示围绕y轴的选择,-90~90(度),从左到右。当设备水平摆放时,gramma此时为0。 **7.2 移动(motion)** **(1)检测是否支持** ``` if(window.DeviceMotionEvent){ //支持 }else{ //不支持 } ``` **(2)和方向事件一样,移动也有监听事件:devicemotion** ``` window.addEventListener('devicemotion',listener,true) function listener(event){ var acceleration = event.acceleration; var accelerationIncludingGravity = event.accelerationIncludingGravity; var rotationRate = event.rotationRate; var interval = event.interval; } ``` 上面代码中,event事件对象有acceleration、accelerationIncludingGravity、rotationRate和interval四个属性。 属性说明: **(1)acceleration、accelerationIncludingGravity** acceleration和accelerationIncludingGravity属性都包含三个轴: x轴:西向东(acceleration.x) y轴:南向北(acceleration.y) z轴:垂直地面(acceleration.z) **(2)rotationRate** rotationRate有三个值: alpha: 设备沿着垂直屏幕的轴的旋转速率 (桌面设备相对于键盘) beta: 设备沿着屏幕左至右方向的轴的旋转速率(桌面设备相对于键盘) gamma: 设备沿着屏幕下至上方向的轴的旋转速率(桌面设备相对于键盘) **(3)interval** interval 表示的是从设备获取数据的频率,单位是毫秒。 更多:检测设备方向 **简单的摇一摇功能:** ``` var SHAKE_THRESHOLD = 3000; var last_update = 0; var x = y = z = last_x = last_y = last_z = 0; if (window.DeviceMotionEvent) { window.addEventListener('devicemotion', deviceMotionHandler, false); } function deviceMotionHandler(eventData) { var acceleration = eventData.accelerationIncludingGravity; var curTime = new Date().getTime(); var diffTime = curTime - last_update; if (diffTime > 100) { last_update = curTime; x = acceleration.x; y = acceleration.y; z = acceleration.z; var speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (speed > SHAKE_THRESHOLD) { //dosomething }; last_x = x; last_y = y; last_z = z; } } ```
';