淘先锋技术网

首页 1 2 3 4 5 6 7

目录

数据类型

数组常用方法

数组迭代方法

Date对象方法

Math 对象方法

正则表达式

js较难语句标识

this 关键词

避免多层 this

避免数组处理方法中的 this

绑定 this 的方法

JavaScript 闭包

JSON方法

定时器

DOM

事件


数据类型

   基本(值)类型

     String: 任意字符串

     Number: 任意的数字

     boolean: true/false

     undefined: undefined

     null: null

   对象(引用)类型

   Object: 任意对象

   Function: 一种特别的对象(可以执行)

   Array: 一种特别的对象(数值下标, 内部数据是有序的)

判断

   typeof:

   可以判断: undefined/ 数值 / 字符串 / 布尔值 / function

   不能判断: null与object  object与array

console.log(typeof null); //Object
console.log(typeof Array); //function
console.log(typeof Object); //function

   instanceof:   判断对象的具体类型

   ===   可以判断: undefined, null

undefined==null    true

undefined=== null    false

数组常用方法

join() 方法也可将所有数组元素结合为一个字符串。它的行为类似 toString(),但是还可以规定分隔符

var str = ["a", "b", "c", "d"];
let s = str.join("*"); //a*b*c*d

pop() 方法从数组中删除最后一个元素,pop() 方法返回“被删除”的值。

push() 方法(在数组结尾处)向数组添加一个新的元素,push() 方法返回新数组的长度。

shift() 方法会删除首个数组元素,shift() 方法返回被“位移出”的字符串。

unshift() 方法(在开头)向数组添加新元素,unshift() 方法返回新数组的长度。

delete 会在数组留下未定义的空洞。请使用 pop() 或 shift() 取而代之。

slice() 方法用数组的某个片段切出新数组

slice() 可接受两个参数,比如 (1, 3)。

如果结束参数被省略,则 slice() 会切出数组的剩余部分

该方法会从开始参数选取元素,直到结束参数(不包括)为止。

var str = ["a", "b", "c", "d", "e"];
var arr = str.slice(1,3); 
console.log(arr) //b,c

splice(a,b,c,d,e) 方法可用于向数组添加新项,

第一个参数(2)定义了应添加新元素的位置(拼接)。

第二个参数(0)定义应删除多少元素。

其余参数(c,d,e)定义要添加的新元素

var str = ["a", "b", "c", "d","e"];
str.splice(2, 0, "x", "y");
console.log(str) //a,b,x,y,c,d,e

concat() 方法通过合并(连接)现有数组来创建一个新数组,不改变原数组。

var str1 = ["a", "b"];
var str2 = ["c", "d", "e"];
var str = str1.concat(str2);
console.log(str) //a,b,c,d,e

reverse() 方法反转数组中的元素。会给变原数组

sort() 函数按照字符串顺序对值进行排序。如果数字按照字符串来排序,则 "25" 大于 "100",因为 "2" 大于 "1"。。通过一个比值函数来修正此问题

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b}); 

比较函数应该返回一个负,零或正值,这取决于参数:

function(a, b){return a-b}
当比较 40 和 100 时,sort() 方法会调用比较函数 function(40,100)。
该函数计算 40-100,然后返回 -60(负值)。
排序函数将把 40 排序为比 100 更低的值。

以随机顺序排序数组

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return 0.5 - Math.random()}); 

数组迭代方法

Array.forEach()

forEach() 方法为每个数组元素调用一次函数(回调函数)

接受 3 个参数:元素值,索引,数组本身

Array.map()

map() 方法通过对每个数组元素执行函数来创建新数组。

map() 方法不会对没有值的数组元素执行函数。

map() 方法不会更改原始数组。

有 3 个参数:元素值,索引,数组本身

Array.filter()

过滤函数

var num = [45, 4, 9, 16, 25];
var arr = num.filter(value=>value > 18)
console.log(arr)  //45,25

filter()方法还可以接受第二个参数,用来绑定参数函数内部的this变量。

var obj = { MAX: 3 };
var myFilter = function (item) {
  if (item > this.MAX) return true;
};

var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj) // [8, 4, 9]

上面代码中,过滤器myFilter()内部有this变量,它可以被filter()方法的第二个参数obj绑定,返回大于3的成员。

链式调用

var users = [
  {name: 'tom', email: '[email protected]'},
  {name: 'peter', email: '[email protected]'}
];

users
.map(function (user) {
  return user.email;
})
.filter(function (email) {
  return /^t/.test(email);
})
.forEach(function (email) {
  console.log(email);
});
// "[email protected]"

Array.reduce()

reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。

reduce() 方法在数组中从左到右工作。

reduce() 方法不会减少原始数组。

var numbers = [1, 2, 3, 4, 5];
var sum = numbers.reduce((total, value, index, array)=>{
	return total + value;
},0);
console.log(sum)  //15

可接受 4 个参数:初始值/先前返回的值,元素值,索引,数组本身

Array.reduceRight()

reduceRight() 方法在每个数组元素上运行函数,以生成(减少它)单个值。

reduceRight() 方法在数组中从右到左工作。

reduceRight() 方法不会减少原始数组。

Array.reduce()不同的就是工作方式

Array.every()

every() 方法检查所有数组值是否通过测试。

Array.some()

some() 方法检查某些数组值是否通过了测试。

Array.indexOf()

indexOf() 方法在数组中搜索元素值并返回其位置。

Array.indexOf(item, start)

item必需。要检索的项目。
start可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到结尾。

如果未找到项目,Array.indexOf() 返回 -1。

如果项目多次出现,则返回第一次出现的位置。

Array.lastIndexOf()

Array.lastIndexOf() 与 Array.indexOf() 类似,但是从数组结尾开始搜索。

Array.lastIndexOf(item, start)

item必需。要检索的项目。
start可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到开头。

Array.find()

find() 方法返回通过测试函数的第一个数组元素的值。

Date对象方法

方法

描述
Date()返回当日的日期和时间。
getDate()从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay()从 Date 对象返回一周中的某一天 (0 ~ 6)。
getMonth()从 Date 对象返回月份 (0 ~ 11)。
getFullYear()从 Date 对象以四位数字返回年份。
getYear()请使用 getFullYear() 方法代替。
getHours()返回 Date 对象的小时 (0 ~ 23)。
getMinutes()返回 Date 对象的分钟 (0 ~ 59)。
getSeconds()返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds()返回 Date 对象的毫秒(0 ~ 999)。
getTime()返回 1970 年 1 月 1 日至今的毫秒数。
parse()返回1970年1月1日午夜到指定日期(字符串)的毫秒数。
setDate()设置 Date 对象中月的某一天 (1 ~ 31)。
setMonth()设置 Date 对象中月份 (0 ~ 11)。
setFullYear()设置 Date 对象中的年份(四位数字)。
setYear()请使用 setFullYear() 方法代替。
setHours()设置 Date 对象中的小时 (0 ~ 23)。
setMinutes()设置 Date 对象中的分钟 (0 ~ 59)。
setSeconds()设置 Date 对象中的秒钟 (0 ~ 59)。
setMilliseconds()设置 Date 对象中的毫秒 (0 ~ 999)。
setTime()以毫秒设置 Date 对象。
toSource()返回该对象的源代码。
toString()把 Date 对象转换为字符串。
toTimeString()把 Date 对象的时间部分转换为字符串。
toDateString()把 Date 对象的日期部分转换为字符串。
toGMTString()请使用 toUTCString() 方法代替。
toLocaleString()根据本地时间格式,把 Date 对象转换为字符串。
toLocaleTimeString()根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleDateString()根据本地时间格式,把 Date 对象的日期部分转换为字符串。
valueOf()返回 Date 对象的原始值。

Math 对象方法

方法描述
abs(x)返回 x 的绝对值
acos(x)返回 x 的反余弦值,以弧度计
asin(x)返回 x 的反正弦值,以弧度计
atan(x)以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x)返回从 x 轴到点 (x,y) 的角度
ceil(x)对 x 进行上舍入
cos(x)返回 x 的余弦
exp(x)返回 Ex 的值
floor(x)对 x 进行下舍入
log(x)返回 x 的自然对数(底为e)
max(x,y,z,...,n)返回最高值
min(x,y,z,...,n)返回最低值
pow(x,y)返回 x 的 y 次幂
random()返回 0 ~ 1 之间的随机数
round(x)把 x 四舍五入为最接近的整数
sin(x)返回 x(x 以角度计)的正弦
sqrt(x)返回 x 的平方根
tan(x)返回角的正切

正则表达式

match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。

该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。

stringObject.match(searchvalue)
stringObject.match(regexp)
参数描述
searchvalue必需。规定要检索的字符串值。
regexp必需。规定要匹配的模式的 RegExp 对象。如果该参数不是 RegExp 对象,则需要首先把它传递给 RegExp 构造函数,将其转换为 RegExp 对象。

在字符串方法 search() 、replace() 中使用正则表达式

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
----------------------------------
var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;
var str = "Visit W3School";
var n = str.search(/w3school/i);   //n=6
----------------------------------------
var str = "Hello XiaoSa!";
var res = str.replace(/xiaosa/i, "潇洒");  //Hello 潇洒

正则表达式中,需要反斜杠转义的,一共有12个字符:^.[$()|*+?{\。需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

修饰符描述
i执行对大小写不敏感的匹配。
g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m执行多行匹配。
元字符描述
.查找单个字符,除了换行和行结束符。
\w查找单词字符。
\W查找非单词字符。
\d查找数字。
\D查找非数字字符。
\s查找空白字符。
\S查找非空白字符。
\b匹配单词边界。
\B匹配非单词边界。
\0查找 NUL 字符。
\n查找换行符。
\f查找换页符。
\r查找回车符。
\t查找制表符。
\v查找垂直制表符。
\xxx查找以八进制数 xxx 规定的字符。
\xdd查找以十六进制数 dd 规定的字符。
\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。
量词描述
n+匹配任何包含至少一个 n 的字符串。
n*匹配任何包含零个或多个 n 的字符串。
n?匹配任何包含零个或一个 n 的字符串。
n{X}匹配包含 X 个 n 的序列的字符串。
n{X,Y}匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,}匹配包含至少 X 个 n 的序列的字符串。
n$匹配任何结尾为 n 的字符串。
^n匹配任何开头为 n 的字符串。
?=n匹配任何其后紧接指定字符串 n 的字符串。
?!n匹配任何其后没有紧接指定字符串 n 的字符串。

js较难语句标识

语句描述
class声明类。
continue如果出现指定条件,则(在循环中)中断一次循环,并继续循环中的下一次迭代。
debugger停止执行 JavaScript,并调用调试功能(如果有)。
for ... in循环遍历对象的属性。
for ... of循环遍历可迭代对象的值。
throw抛出(生成)错误。
try ... catch ... finally标记在 try 块中发生错误时要执行的语句块,并实现错误处理。

this 关键词

this 关键词指的是它所属的对象

  • 在方法中,this 指的是所有者对象。
  • 单独的情况下,this 指的是全局对象。
  • 在函数中,this 指的是全局对象。
  • 在函数中,严格模式下,this 是 undefined。
  • 在事件中,this 指的是接收事件的元素。

下面这几种用法,都会改变this的指向。

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window

上面代码中,obj.foo就是一个值。这个值真正调用的时候,运行环境已经不是obj了,而是全局环境,所以this不再指向obj

可以这样理解,JavaScript 引擎内部,objobj.foo储存在两个内存地址,称为地址一和地址二。obj.foo()这样调用时,是从地址一调用地址二,因此地址二的运行环境是地址一,this指向obj。但是,上面三种情况,都是直接取出地址二进行调用,这样的话,运行环境就是全局环境,因此this指向全局环境。

避免多层 this

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object
// Window

上面代码包含两层this,结果运行后,第一层指向对象o,第二层指向全局对象,因为实际执行的是下面的代码。

var temp = function () {
  console.log(this);
};

var o = {
  f1: function () {
    console.log(this);
    var f2 = temp();
  }
}

一个解决方法是在第二层改用一个指向外层this的变量。

var o = {
  f1: function() {
    console.log(this);
    var _this = this;
    var f2 = function() {
      console.log(_this );
    }();
  }
}

o.f1()
// Object
// Object

上面代码定义了变量_this,固定指向外层的this,然后在内层使用_this,就不会发生this指向的改变。

避免数组处理方法中的 this

数组的mapforeach方法,允许提供一个函数作为参数。这个函数内部不应该使用this

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    });
  }
}

o.f()
// undefined a1
// undefined a2

 上面代码中,foreach方法的回调函数中的this,其实是指向window对象,因此取不到o.v的值。原因跟上一段的多层this是一样的,就是内层的this不指向外部,而指向顶层对象。

解决这个问题的一种方法,就是前面提到的,使用中间变量固定this。(不再赘述)

另一种方法是将this当作foreach方法的第二个参数,固定它的运行环境。

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    }, this);
  }
}

o.f()
// hello a1
// hello a2

绑定 this 的方法

JavaScript 提供了callapplybind这三个方法,来切换/固定this的指向。

call() 和 apply() 这样的方法可以将 this 引用到任何对象。

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true

全局环境运行函数f时,this指向全局环境(浏览器为window对象);call方法可以改变this的指向,指定this指向对象obj,然后在对象obj的作用域中运行函数fcall方法的参数,应该是一个对象。如果参数为空、nullundefined,则默认传入全局对象

call方法的一个应用是调用对象的原生方法。

var obj = {};
obj.hasOwnProperty('toString') // false

// 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty('toString') // true

Object.prototype.hasOwnProperty.call(obj, 'toString') // false

上面代码中,hasOwnPropertyobj对象继承的方法,如果这个方法一旦被覆盖,就不会得到正确结果。call方法可以解决这个问题,它将hasOwnProperty方法的原始定义放到obj对象上执行,这样无论obj上有没有同名方法,都不会影响结果。

call() 和 apply() 之间的区别

不同之处是:

call() 方法分别接受参数。

apply() 方法接受数组形式的参数。

JavaScript 不提供找出数组最大元素的函数。结合使用apply方法和Math.max方法,就可以返回数组的最大元素。

var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15
--------------------------
Math.max(...a) //15

将数组的空元素变为undefined

Array.apply(null, ['a', ,'b'])
// [ 'a', undefined, 'b' ]

空元素与undefined的差别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined。因此,遍历内部元素的时候,会得到不同的结果。

var a = ['a', , 'b'];

function print(i) {
  console.log(i);
}

a.forEach(print)
// a
// b

Array.apply(null, a).forEach(print)
// a
// undefined
// b

利用数组对象的slice方法,可以将一个类数组(比如arguments对象)转为真正的数组。

Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
//这个方法起作用的前提是,被处理的对象必须有length属性,以及相对应的数字键

bind()方法

bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。

var d = new Date();
d.getTime() // 1630997335855

var print = d.getTime
print() //this is not a Date object

上面代码报错了,是因为getTime()方法内部的this,绑定Date对象的实例,赋给变量print以后,内部的this已经不指向Date对象的实例了。

//解决方案
var d = new Date();
var print = d.getTime.bind(d);
print() //1630997335855

上面代码中,bind()方法将getTime()方法内部的this绑定到d对象,这时就可以安全地将这个方法赋值给其他变量了。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc.bind(counter);
func();
counter.count // 1

上面代码中,counter.inc()方法被赋值给变量func。这时必须用bind()方法将inc()内部的this,绑定到counter,否则就会出错。

var add = function (x, y) {
  return x * this.m + y * this.n;
}

var obj = {
  m: 2,
  n: 2
};

var newAdd = add.bind(obj, 5);
console.log(newAdd(4));//18

上面代码中,bind()方法除了绑定this对象,还将add()函数的第一个参数x绑定成5,然后返回一个新函数newAdd(),这个函数只要再接受一个参数y就能运行了。

bind()方法有一些使用注意点。

bind()方法每运行一次,就返回一个新函数,这会产生一些问题。比如,监听事件的时候,不能写成下面这样。

element.addEventListener('click', o.m.bind(o));

click事件绑定bind()方法生成的一个匿名函数。这样会导致无法取消绑定

//应该这样写
var listener = o.m.bind(o);
element.addEventListener('click', listener);
//  ...
element.removeEventListener('click', listener);
var obj = {
  name: '潇洒',
  times: [1, 2, 3],
  print: function () {
    this.times.forEach(function (n) {
      console.log(this.name);
    });
  }
};

obj.print()
// 没有任何输出
--------------------------
//改写print方法
print :function () {
    this.times.forEach(function (n) {
      console.log(this.name);
    }.bind(this));
  }
obj.print()//潇洒 潇洒 潇洒

obj.print内部this.timesthis是指向obj的,这个没有问题。但是,forEach()方法的回调函数内部的this.name却是指向全局对象,导致没有办法取到值。

JavaScript 闭包

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// 计数器目前是 3 

变量 add 的赋值是自调用函数的返回值。

这个自调用函数只运行一次。它设置计数器为零(0),并返回函数表达式。

这样 add 成为了函数。最“精彩的”部分是它能够访问父作用域中的计数器。

这被称为 JavaScript 闭包。它使函数拥有“私有”变量成为可能。

计数器被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。

闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。

JSON方法

方法描述
parse()解析 JSON 字符串并返回 JavaScript 对象。
stringify()将 JavaScript 对象转换为 JSON 字符串。

JSON.parse()方法用于将 JSON 字符串转换成对应的值。

JSON.parse()方法可以接受一个处理函数,作为第二个参数,用法与JSON.stringify()方法类似。

function f(key, value) {
  if (key === 'a') {
    return value + 10;
  }
  return value;
}

JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}

上面代码中,JSON.parse()的第二个参数是一个函数,如果键名是a,该函数会将键值加上10。

如果对象的属性是undefined、函数或 XML 对象,该属性会被JSON.stringify()过滤。

var obj = {
  a: undefined,
  b: function () {}
};

JSON.stringify(obj) // "{}"

上面代码中,对象obja属性是undefined,而b属性是一个函数,结果都被JSON.stringify过滤。

如果数组的成员是undefined、函数或 XML 对象,则这些值被转成null

var arr = [undefined, function () {}];
JSON.stringify(arr) // "[null,null]"

上面代码中,数组arr的成员是undefined和函数,它们都被转成了null

正则对象会被转成空对象。

JSON.stringify(/xiaosa/) // "{}"

JSON.stringify()方法会忽略对象的不可遍历的属性。

var obj = {};
Object.defineProperties(obj, {
  'foo': {
    value: 1,
    enumerable: true
  },
  'bar': {
    value: 2,
    enumerable: false
  }
});

JSON.stringify(obj); // "{"foo":1}"

定时器

如果回调函数是对象的方法,那么setTimeout使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象。

var x = 1;

var obj = {
  x: 2,
  y: function () {
    console.log(this.x);
  }
};

setTimeout(obj.y, 1000) // 1

上面代码输出的是1,而不是2。因为当obj.y在1000毫秒后运行时,this所指向的已经不是obj了,而是全局环境。

一种解决方法是将obj.y放入一个函数。

var x = 1;

var obj = {
  x: 2,
  y: function () {
    console.log(this.x);
  }
};

setTimeout(function () {
  obj.y();
}, 1000);
// 2

上面代码中,obj.y放在一个匿名函数之中,这使得obj.yobj的作用域执行,而不是在全局作用域内执行,所以能够显示正确的值。

debounce防抖 短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。

function debounce(fn, delay){
  var timer = null; // 声明计时器
  return function() {
    var context = this;
    var args = arguments;
    if(timer) clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

throttle节流 在 一定时间 之内,限制 一个动作  执行一次 

function throttle(fn,wait){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                fn.apply(context,args);
                timer = null;
            },wait)
        }
    }
}

等到当前脚本的同步任务,全部处理完以后,才会执行setTimeout指定的回调函数f。也就是说,setTimeout(f,0))会在下一轮事件循环一开始就执行。promise.then()比setTimeout(f,0)执行早,因为promise.then(f,0)是本轮事件循环执行,setTimeout(f,0)在下一轮事件循环开始时执行

setTimeout(function () {
  console.log(1);
}, 0);
console.log(2);
// 2
// 1

DOM

Node接口

Node 对象定义了几个常量,对应这些类型值。

document.nodeType === Node.DOCUMENT_NODE // true

文档节点(document):9,对应常量Node.DOCUMENT_NODE

元素节点(element):1,对应常量Node.ELEMENT_NODE

属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE

文本节点(text):3,对应常量Node.TEXT_NODE

Node.prototype.nodeName   返回节点的名称。

// <div id="d1">hello world</div>
var div = document.getElementById('d1');
div.nodeName // "DIV"

Node.prototype.nodeValue   返回一个字符串,表示当前节点本身的文本值,该属性可读写。

// <div id="d1">hello world</div>
var div = document.getElementById('d1');
div.nodeValue // null
div.firstChild.nodeValue // "hello world"

上面代码中,div是元素节点,nodeValue属性返回nulldiv.firstChild是文本节点,所以可以返回文本值。

Node.prototype.textContent  返回当前节点和它的所有后代节点的文本内容

Node.prototype.baseURL  返回一个字符串,表示当前网页的绝对路径。浏览器根据这个属性,计算网页上的相对路径的 URL。该属性为只读

Node.prototype.nextSibling   Node.prototype.previousSibling   Node.prototype.parentNode 等等,详细可看Node 接口 - JavaScript 教程 - 网道

事件

EventTarget.addEventListener()用于在当前节点或对象上(即部署了 EventTarget 接口的对象),定义一个特定事件的监听函数。一旦这个事件发生,就会执行监听函数。该方法没有返回值。

target.addEventListener(type, listener[, useCapture]);

type:事件名称,大小写敏感。listener:监听函数。useCapture:布尔值,如果设为true,表示监听函数将在捕获阶段(capture)触发。默认值为false(监听函数只在冒泡阶段被触发)。

一个事件发生后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段。

第一阶段:从window对象传导到目标节点(上层传到底层),称为“捕获阶段”(capture phase)。

第二阶段:在目标节点上触发,称为“目标阶段”(target phase)。

第三阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。

Event.preventDefault()方法取消浏览器对当前事件的默认行为。比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了

// <input type="checkbox" id="my-checkbox" />
var cb = document.getElementById('my-checkbox');

cb.addEventListener(
  'click',
  function (e){ e.preventDefault(); },
  false
);

上面代码中,浏览器的默认行为是单击会选中单选框,取消这个行为,就导致无法选中单选框。