javascript经典实例笔记

第一章

使用内置对象创建的变量(不带关键词new),严格等于字面量

1
2
3
4
5
var str1 = 'abc';
var str2 = String('abc');
str1 === str2; // true
typeof str1; // string
typeof str2; // string

使用new创建的变量,松散等于字面量,不严格等于字面量

1
2
3
4
5
6
var str1 = 'abc';
var str2 = new String('abc');
str1 == str2; // true
str1 === str2; // false
typeof str1; // string
typeof str2; // object

访问基本类型的属性时,javascript引擎会模拟创建一个临时对象来包围基本类型,属性访问之后引擎会立马丢弃这个临时对象。这正是“基本类型不是对象,但仍可以放问它的一些属性”的原因。

1
2
3
4
var str = 'abc';
str.length; // 3
str.length = 4; // 为基本类型添加属性,其实是加在了临时对象上。该赋值没有意义,这行代码执行后,临时对象立刻被丢弃。
str.length; // 3

indexOf 使用方式为 str.indexOf(searchValue, fromIndex)searchValue 为要查询的字符串, fromIndex第 二个参数为起始查询点。
特殊情况:

  1. 如果 searchValue为空白,即 indexOf() ,searchValue 会被当做字符串 undefined 。
1
"0123undefined".indexOf(); // 4
  1. 如果 searchValue 为空字符串,结果取决于 fromIndex:
1
2
3
"abc".indexOf(''); // 0 如果fromIndex为空白,或者小于等于0 ,返回 0
"abc".indexOf('', 1); // 1 如果fromIndex 大于 0 且小于等于 str.length,返回 fromIndex
"abc".indexOf('', 10); // 3 如果fromIndex 大于 str.length ,返回 str.length

可以从一个Date减去另一个Date,两者的差值以毫秒返回。然而如果把两个日期相加,结果是第二个日期附加到第一个日期后面的一个字符串。

如果把两个Date对象相除,需要把Date转换为毫秒值,返回相除的结果。将两个日期相乘,会返回一个非常大的毫秒值。

1
2
3
4
5
6
7
8
var firstDate = new Date();
setTimeout(function(){
var secondDate = new Date();
console.log(secondDate + firstDate); // Thu Nov 21 2019 16:40:16 GMT+0800 (中国标准时间)Thu Nov 21 2019 16:40:13 GMT+0800 (中国标准时间)
console.log(secondDate - firstDate); // 近似等于2500
console.log(secondDate * firstDate); // 2.4785011416546957e+24
console.log(secondDate / firstDate); // 1.0000000015879815
},2500)

lastIndexOf是从尾部到头部进行搜索,如果给定搜索的起始位置(即第二个参数),则从起始位置向头部进行搜索,返回找到的第一个元素的索引。

1
2
3
var arr = ['a','b','c','a'];
arr.lastIndexOf('a'); // 3 从尾到头进行搜索字母a,首先搜到索引为3的a
arr.lastIndexOf('a', 2); // 0 从索引2位置向头部进行搜索字母a,首先搜到索引为0的a

splice方法接受到的索引如果为负数,则从末尾开始对数组/字符串操作,-n相当于从倒数第n个位置进行操作。如果没有接受到第二个参数,则一直删除到底。

1
2
3
var arr = ['a','b','c'];
arr.splice(-2, 1); // ["b"] 从倒数第二个位置即字母b,删除一个元素,一共删除了字母b
arr.splice(-2); // ["b", "c"] 从倒数第二个位置即字母b,一直删除到底,一共删除了b和c

第二章

dict模式:创建拥有一个空的原型的对象,以避免已有的属性可能会搞乱程序。

1
2
3
4
5
var obj = {};
var newObj = Object.create(null);
var key = 'toString';
console.log(key in obj); // true 解答:toString是一个标准的Object方法
console.log(key in newObj); // false

第三章

可以通过字面值函数为函数提供一个名称,但这个名称只能在函数内部用

1
2
3
var fn = function name(){type of name};
fn(); // "function"
name(); // Uncaught SyntaxError 解读:函数名name只能在函数内部访问到

使用slicecall可以将类数组或NodeList转换为数组。

1
2
[].slice.call(arguments);
[].slice.call(NodeList);

第四章

继承一个对象的方式: Object.create()apply

1
2
3
4
5
6
7
8
9
10
11
12
function Parent(){
this.name = 'js';
};
Parent.prototype.age = 24;
function Child(){};
//方式一
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
//方式二
function Child(){
Parent.apply(this,arguments);
};

让方法链化的关键一步是,在方法尾部返回对象(使用该方法的对象)的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
function Book(){
this.setTitle = function(title){
this.title = title;
return this;
}
this.setAuthor = function(author){
this.author = author;
return this;
}
}
var book = new Book();
book.setTitle('js').setAuthor('Jorn');
console.log(book.author); // Jorn

第五章

NodeList唯一可使用的属性为length,唯一方法为item。不能直接对NodeList使用Array方法,比如push。

DOM的style属性只能获取到内联样式,style标签以及样式表中的样式,无法通过.style方式获取。可以使用getComputedStyle去获取元素所有当前生效的样式。

display:none会从页面布局中完全删除元素,而visibility:hidden只是视觉上隐藏了元素,仍然会影响其他元素的布局。

第八章

在JSON中,如果对象包含其他对象,其他对象会被转换为JSON的等价形式。

1
2
3
var obj = {name:"obj"};
var newObj = {name:"newObj",other:obj};
JSON.stringify(newObj); // "{"name":"newObj","other":{"name":"obj"}}"

第九章

向SVG添加JavaScript,必须提供style属性。并且要把脚本包含在CDATA块中,否则XML会把<当做XML而不是脚本对待。

1
2
3
4
5
<script type='text/ecmascript'>
<![CDATA[
var name = 'js';
]]>
</script>

访问svg元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<object id='object' data='demo.svg'></object>
<script>
var object = document.getElementById('object');
object.onload=function(){
var svgdoc;
try{
svgdoc = object.contentDocument;
}catch(error){
try{
svgdoc = object.getSVGDocument();
}catch(error){
alert('SVG Not Support');
}
}
}
</script>

Math.round中间值(0.5)向较大数取值,所以Math.round(-1.5)为-1,而不是-2

在获取画布的imageData时常常会发生如下错误:Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data 增加一个img.crossOrigin = ''即可解决这个问题。

video元素有个timeupdate事件,每200毫秒触发一次。

虽然NaN不等于自身,但是对于使用NaN作为键的Map对象,NaN是和自身相等的:

1
2
3
4
var myMap= new Map();
myMap.set(NaN,'nan');
var key = Number('not a number');
console.log(myMap.get(key)); // 'nan'

使用数组作为键的Map对象,必须使用完全相同的键才能获取到响应的键值:

1
2
3
4
5
6
var arr = [1,2];
var arr2 = arr;
var myMap = new Map();
myMap.set(arr,'12');
console.log(myMap.get([1,2])); // undefined
console.log(myMap.get(arr2)); // '12'

第十二章

通用模块定义UMD

1
2
3
4
5
6
7
8
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.moduleName = factory());
}(this, function () {
'use strict';
// TODO
}

某个package.json文件中,用npm remove命令移出dependencies(或devDependencies)中的最后一项,属性dependencies并不会被一并删除,只是将其设为一个空值。

1
"dependencies":{}

第十三章

Worker 线程的一个缺点,就是并不是所有的内建对象或功能都能在所有的浏览器中可用。比如在旧版本的Firefox中,异步的FileReader不会在Worker线程中工作。

第十四章

Shadow DOM,即这部分 DOM 默认与外部 DOM 隔离,内部任何代码都无法影响外部。

Web Component https://jsfiddle.net/zhaohd/vfbnLeaz/

第十五章

要使用GET、POST 或HEAD之外的一个方法,必须对你的请求预检(preflight)。

江山父老能容我,不使人间造孽钱