JS不了解的知识点
您可以在这里记录工作中用到的知识
标签语句
语句是可以添加标签的,标签是由语句前的标识符和冒号组成:
label : statement
label语句定义的标签一般由break或continue语句引用。加标签的语句一般要与for等循环语句配合使用。
var num = 0;
tip : for(var i = 0; i < 10; i++){
num += i;
console.log(i); // 轮流输出:0、1、2、3、4、5
if(i ==5) {
break tip;
}
}
console.log(num); // 15
当执行到i=5时,会跳出循环,也就是tip对应的层,然后执行其下方的代码。
with语句
with
语句用于临时扩展作用域链,也就是将代码的作用域设置到一个特定的对象中。
with(object){
statement
}
将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原生状态。
var o = {
name: 'tg',
age: 24
};
with(o){
console.log('name:' + name); // name:tg
console.log('age:' + age); // age:24
}
with里面的name相当于o.name。
debugger语句
debugger语句用来产生一个断点(breakpoint),JavaScript代码的执行会停止在断点的位置。一般用来调试代码。
对象
对象是一种复合值:它将很多值聚合子啊一起,可通过名字访问这些值。对象也可看做一种无序的数据集合,由若干个“键值
对”(key-value)构成。
var o={
name:'a'
}
上面代码中,大括号定义了一个对象,它被赋值给变量o。这个对象内部包含一个键值对(又称为“成员”),name是“键名”(成员的名称),字符串a是“键值”(成员的值)。
键名与键值之间用冒号分隔。如果对象内部包含多个键值对,每个键值对之间用逗号分隔。
读取属性
读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。
var o = {
name : 'a'
}
o.name // "a"
o['name'] //"a"
for…in
for…in循环用来遍历一个对象的全部属性。
var o = {
name : 'a',
age : 12
}
for(var i in o){
console.log(o[i]
}
// "a"
// 12
查看所有属性
查看一个对象本身的所有属性,可以使用Object.keys方法,返回一个数组。
var o = {
name : 'a',
age : 12
}
Object.keys(o) //['name','age']
删除属性
delete运算符可以删除对象的属性。
var o={
name : 'a'
}
delete o.name //true
o.name //undefined
hasOwnPreperty()方法
用于判断一个对象自身(不包括原型链)是否具有指定名称的属性。如果有,返回true,否则返回false。
propertyIsEnumerable()方法
只有检测到是自有属性且这个属性的可枚举性为true时才返回true。
in运算符
in运算符左侧是属性名(字符串),右侧是对象。如果对象的自有属性或继承属性中包含这个属性就返回true。
var o = {
name : 'a'
}
'name' in o //true
对象的三个属性
每一个对象都有与之相关的原型(prototype)、类(class)和可扩展性(extensible attribute)
将对象作为参数传入Object.getPrototypeOf()可以查询它的原型。
检测一个对象是否是另一个对象的原型,可以使用isPrototypeOf()方法。
序列化对象
对象序列化是指将对象的状态转换为字符串,也可将字符串还原为对象。
在JavaScript中,提供了内置函数JSON.stringify()和JSON.parse()用来序列化和还原JavaScript对象。NaN、Infinity和-Infinity序列化的结果是null
var o = {
name : 'a',
age : 12,
intro : [false,null,'']
}
s= JSON.stringify(o) // s {"name":"a","age":12,"intro":[false,null,""]}
p=JSON.parse(s) // p是o的深拷贝
this关键字
this总是返回一个对象,简单说,就是返回属性或方法“当前”所在的对象。
this.property
上面的代码中,this就代表property属性当前所在的对象。
由于对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this的指向是可变的。
var A = {
name: '张三',
describe: function(){
return this.name;
}
};
var B = {
name: '李四'
};
B.describe = A.describe;
B.describe();
// "李四"
改变this指向
在JavaScript中,提供了call、apply、bind三种方法改变this的指向。
funciton.prototype.call()
call(obj, arg1, arg2, ...)
第一个参数obj是this要指向的对象,也就是想指定的上下文;arg1,arg2…都是要传入的参数。
funciton.prototype.apply()
apply(obj,[arg1,arg2....])
apply()和call()方法原理类似,只不过,它第二个参数一个数组,里面的值就是要传入的参数。
function.prototype.bind()
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
bind(obj)
原型
每一个JavaScript对象(null除外)都和另一个对象相关联,也可以说,继承另一个对象。另一个对象就是我们熟知的“原型”(prototype),每一个对象都从原型继承属性。只有null除外,它没有自己的原型对象。
所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码Object.prototype获得对原型对象的引用。
通过关键字new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值。比如:通过new Object()创建的对象继承自Object.prototype;通过new Array()创建的对象的原型就是Array.prototype。
没有原型的对象为数不多,Object.prototype就是其中之一,它不继承任何属性。
所有的内置构造函数都具有一个继承自Object.prototype的原型。
原型链
对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。比如,a对象是b对象的原型,b对象是c对象的原型,以此类推。
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性指向的那个对象。那么,Object.prototype对象有没有它的原型呢?回答可以是有的,就是没有任何属性和方法的null对象,而null对象没有自己的原型。
“原型链”的作用:
当读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。
继承
JavaScript对象具有“自有属性”,也有一些属性是从原型对象继承而来的。
当查询一个不存在的属性时,JavaScript不会报错,返回undefined。
如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overiding)。
contructor属性
prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。
instanceof运算符
instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。
var c = new Car();
c instanceof Car //true
instanceof运算符的左边是实例对象,右边是构造函数。它的运算实质是检查右边构建函数的原型对象,是否在左边对象的原型链上。
Object.getPrototypeOf()
Object.getPrototypeOf方法返回一个对象的原型。这是获取原型对象的标准方法
Object.getPrototypeOf(c) === Car.prototype //true
Object.setPrototypeOf()
Object.setPrototypeOf方法可以为现有对象设置原型,返回一个新对象。Object.setPrototypeOf方法接受两个参数,第一个 是现有对象,第二个是原型对象。
Object.create()
Object.create方法用于从原型对象生成新的实例对象,可以替代new命令。 它接受一个对象作为参数,返回一个新对象,后者完全继承前者的属性,即原有对象成为新对象的原型。
Object.prototype.isPrototypeOf()
对象实例的isPrototypeOf方法,用来判断一个对象是否是另一个对象的原型。
Object.prototype.isPrototypeOf({}) //true
Object.prototype.proto
__proto__属性(前后各两个下划线)可以改写某个对象的原型对象。
Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回一个数组,成员是对象本身的所有属性的键名,不包含继承的属性键名。
Object.prototype.hasOwnProperty()
对象实例的hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
数组长度
length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。
var arr = [1,2,3]
arr.length //3
arr.length = 2;
arr //[1,2]
将数组清空的一个有效方法,就是将length属性设为0。
如果人为设置length大于当前元素个数,则数组的成员数量会增加到这个值,新增的位置都是空位。
稀疏数组
稀疏数组是指包含从0开始的不连续索引的数组。通常,数组的length属性值代表数组中元素的个数,但如果是稀疏数组,length属性值大于元素的个数。
多维数组
JavaScript不支持真正的多维数组,但可以用数组的数组来近似。也可以说,数组里放数组。
var arr = [[1],[2,3]];
arr[0][0] // 1
arr[1][1] //3
类数组对象
在JavaScript中,有些对象被称为“类数组对象”。意思是,它们看上去很像数组,可以使用length属性,但是它们并不是数组,无法使用一些数组的方法。
var o = {
0: 'a',
1: 'b',
length:2
}
o[0] // "a"
o[1] // "b"
o.length // 2
o.push('d') // TypeError: o.push is not a function
上面代码中,变量o是一个对象,虽然使用的时候看上去跟数组很像,但是无法使用数组的方法。这就是类数组对象。
类数组对象 有一个特征,就是具有length属性。换句话说,只要有length属性,就可以认为这个对象类似于数组。但是,对象的length属性不是动态值,不会随着成员的变化而变化。
由于类数组对象没有继承自Array.prototype,那就不能在它们上面直接调用数组方法。不过我们可以间接的使用Function.call方法调用。
var o = {
0: 'a',
1: 'b',
length:2
};
Array.prototype.slice.call(o) // ["a","b"]
典型的类似数组的对象是函数的arguments对象,以及大多数DOM元素集,还有字符串。
函数定义(声明)
JavaScript有三种方法,可以定义一个函数。
function命令
function name() {}
name是函数名称标识符。函数名称是函数声明语句必需的部分。不过对于函数表达式来说,名称是可选的:如果存在,该名字只存在于函数体内,并指向该函数对象本身。
圆括号:圆括号内可放置0个或多个用逗号隔开的标识符组成的列表,这些标识符就是函数的参数名称。 花括号:可包含0条或多条JavaScript语句。这些语句构成了函数体。一旦调用函数,就会执行这些语句。
函数表达式
var f = function(x){
console.log(x);
}
采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。
Function()
Function()函数定义还可以通过Function()构造函数来定义
var f=new Function('x','y','return x+y');
等价于
var f=function(x,y){
return x+y;
}
除了最后一个参数是函数体外,前面的其他参数都是函数的形参。如果函数不包含任何参数,只须给构造函数简单的传入一个字符串—函数体—即可。 不过,Function()构造函数在实际编程中很少会用到。
嵌套函数
JavaScript的函数可以嵌套在其他函数中定义,这样它们就可以访问它们被定义时所处的作用域中的任何变量,这就是JavaScript的 闭包 。
function test(){
var name = 'tg';
function test2(){
var age = 10;
console.log(name); // "tg"
}
console.log(age); // Uncaught ReferenceError: age is not defined
}
test();
从上面的例子可得,test2()可以访问name,但是如果在test()内,test2()外访问age,就会报错。
函数调用
构成函数主体的JavaScript代码在定义时并不会执行,只有调用该函数,它们才会执行。有4种方式调用JavaScript函数:
-
作为函数
-
作为方法
-
作为构造函数
-
通过它们的call()和apply()方法间接调用
可选形参
在ECMAScript中的函数在调用时,传递的参数可少于函数中的参数,没有传入参数的命名参数的值是undefined。为了保持好的适应性,一般应当给参数赋予一个合理的默认值。
function go(x,y){
x = x || 1;
y = y || 2;
}
注意:当用这种可选实参来实现函数时,需要将可选实参放在实参列表的最后。那些调用你的函数的程序员是没法省略第一个参数并传入第二个实参的。
实参对象
当调用函数时,传入的实参个数超过函数定义时的形参个数时,是没有办法直接获得未命名值的引用。 这时,标识符**** 出现了,其指向实参对象的引用,实参对象是一个类数组对象,可以通过数字下标来访问传入函数的实参值,而不用非要通过名字来得到实参。
function go(x){
console.log(arguments[0]);
console.log(arguments[1]);
}
go(1,2);
//1
//2
arguments
有一个 length
属性,用以标识其所包含元素的个数。
function f(x){
console.log(arguments.length);
}
f(1,2) // 2
在函数体内,我们可以通过 arguments
对象来访问这个参数类数组,我们可以使用方括号语法访问它的每一个参数(比如arguments[0]),它还有一个length属性,表示传递进来的参数个数。
arguments
类数组中每一个元素的值会与对应的命名参数的值保持同步,这种影响是单向的,也可以这样说,如果是修改arguments
中的值,会影响到命名参数的值,但是修改命名参数的值,并不会改变 arguments
中对应的值。(不是太理解,总觉得是错的)
function f(x){
console.log(x); // 1
arguments[0]=null;
console.log(x); // null
}
f(1);
在上面的例子中,arguments[0]和x指代同一个值,修改其中一个的值会影响到另一个。 注意:如果有同名的参数,则取最后出现的那个值。
function f(x,x){
console.log(x);
}
f(1,2) // 2
callee
和 caller
属性
arguments
对象带有一个 callee
属性,返回它所对应的原函数。
在一个函数调用另一个函数时,被调用函数会自动生成一个 caller 属性,指向调用它的函数对象。如果该函数当前未被调用,或并非被其他函数调用,则 caller 为null。
再次提醒, arguments 并不是真正的数组,它只是类数组对象(有length属性且可使用索引来访问子项)。但我们可以借助Array类的原型对象的slice方法,将其转为真正的数组:
Array.prototype.slice.call(arguments, 0);
//更简洁的写法
[].slice.call(arguments, 0);
按值传参
在向参数传递引用类型的值时,会先把这个值在内存中的地址复制给一个局部变量,若局部变量变化,则局部变量和复制给局部变量路径的全局变量也会发生改变。
function test(obj){
obj.name = 'tg';
}
var person = new Object();
test(person);
console.log(person.name); // "tg"
但是,如果局部变量指向了一个新的堆内地址,再改变局部变量的属性时,不会影响全局变量。
function test(obj){
obj.name = 'tg';
obj = new Object();
obj.name = 'tg2';
}
var person = new Object();
test(person);
console.log(person.name); // "tg"
在上面的例子中,全局的 person 和函数内局部的 obj 在初始传递时,两者指向的是内存中的同一个地址,但是,当在函数内创建了一个新的对象,并赋值给 obj (赋值的是新对象的地址)。这个时候, obj 指向的就不在是全局对象 person,而是指向了新对象的地址,所以给obj添加属性name时,全局对象person的属性不会被改变。
对于上面的例子中的obj,也可以这样说,一旦obj的值发生了变化,那么它就不再指向person在内存中的地址了。
将对象属性用做实参
当一个函数包含超过三个形参时,要记住调用函数中实参的正确顺序是件让人头疼的事。不过,我们可以通过名/值对的形式传入参数,这样就不需要管参数的顺序了。
function f(params){
console.log(params.name);
}
f({name:'a'})
没有重载
ECMAScript函数没有重载的定义。
重载是指为一个函数编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。
对于ECMAScript函数,如果定义了两个同名的,后定义的函数会覆盖先定义的函数。
函数属性、方法和构造函数
name属性
name属性返回紧跟在function关键字之后的那个函数名。
function f(){}
f.name //f
length属性
函数的length属性是只读属性,代表函数形参的数量,也就是在函数定义时给出的形参个数。
function f(x,y){}
f.length //2
prototype属性
每一个函数都包含一个prototype属性,这个属性指向一个对象的引用,这个对象称做“原型对象”(prototype object)。
call()
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由thisObj 指定的新对象。
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;
//}
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
构造函数
构造函数和普通函数的定义并没有太大区别,不过我们使用 new 关键字来生成构造函数的实例对象。
function Test(){}
var t = new Test();
对于构造函数,一般首字母大写,便于和普通函数区别开来。
定义每个函数都会主动获取一个 prototype 属性,该属性拥有一个对象–该函数的原型,该原型有一个 constructor 属性,指向其当前所属的函数。
闭包
JavaScript的函数可以嵌套在其他函数中定义,这样它们就可以访问它们被定义时所处的作用域中的任何变量,这就是JavaScript的 闭包 。
闭包 会保存函数作用域中的状态,即使这个函数已经执行完毕。
闭包 的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即 闭包 可以使得它诞生环境一直存在。
闭包 的创建依赖于函数。
function f(a){
return function(){
return a++;
};
}
var c=f(1);
console.log(c()); //1
console.log(c()); //2
console.log(c()); //3
闭包的另一个用处,是封装对象的私有属性和私有方法。
立即调用的函数表达式(IIFE)
在Javascript中,一对圆括号()是一种运算符,跟在函数名之后,表示调用该函数。
(function(){
statement
}())
上面的函数会立即调用。
当然,下面的方法也会以表达式来处理函数定义的方法。
!function(){}();
~function(){}();
-function(){}();
+function(){}();
通常情况下,只对匿名函数使用这种“立即执行的函数表达式”。它的目的有两个:
-
一是不必为函数命名,避免了污染全局变量;
-
二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
eval命令
eval命令的作用是,将字符串当作语句执行。
eval('var a=1');
a //1
eval没有自己的作用域,都在当前作用域内执行
JavaScript规定,如果使用严格模式,eval内部声明的变量,不会影响到外部作用域。
(function(){
'use strict';
eval('var a=1');
console.log(a); //ReferenceError: a is not defined
})();
严格模式下的函数
-
不能把函数命名为eval或arguments
-
不能把参数命名为eval或arguments
-
不能出现两个命名参数同名的情况
如果出现上面三种情况,都会导致语法错误,代码无法执行。
Object对象的静态方法
Object.keys()、Object.getOwnPropertyNames()
Object.keys()
方法和 Object.getOwnPropertyNames()
方法一般用来遍历对象的属性,它们的参数都是一个对象,返回一个数组,该数组的项都是对象自身的(不是继续原型的)的所有属性名。两者的区别在于, Object.keys()
只返回可枚举的属性, Object.getOwnPropertyNames()
方法还返回不可枚举的属性名。
var arr = ['a', 'b'];
console.log(Object.keys(arr)); // ["0", "1"]
console.log(Object.getOwnPropertyNames(arr)); // ["0", "1", "length"]
数组的length属性是不可枚举的。
Object对象的实例方法
valueOf()//返回当前对象对应的值,默认情况下返回对象本身。
toString()//返回当前对象对应的字符串形式。
toLocaleString()//返回当前对象对应的本地字符串形式。
hasOwnProperty()//判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。 如果是自身的属性,返回true,否则返回false。
isPrototypeOf()//判断当前对象是否为另一个对象的原型。如果是,返回true,否则返回false。
propertyIsEnumerable()//判断某个属性是否可枚举。
Array实例的方法
join()
以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔。
var arr = [1, 'test'];
console.log(arr.join());
console.log(arr.join('||'));
shift()
用于删除数组的第一个元素,并返回该元素,该方法会改变原数组。
var arr = [1,'test'];
console.log(arr.shift()); // 1
console.log(arr); // ["test"]
unshift()
用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度,该方法会改变原数组。
var arr = [1,'test'];
console.log(arr.unshift('a')); // 3
console.log(arr); // ["a", 1, "test"]
unshift() 可添加多个元素:
var arr = [1,'test'];
console.log(arr.unshift('a','b')); // 4
reverse()
reverse() 用于颠倒数组中元素的顺序,返回改变后的数组,该方法会改变原数组。
var arr = [1,'test'];
console.log(arr.reverse()); // ["test",1]
slice()
slice() 用于提取原数组的一部分,返回一个新数组,原数组不变。
第一个参数为起始位置(从0开始),如参数是负数,则表示倒数计算的位置。
第二个参数为终止位置(但该位置的元素本身不包括在内),如参数是负数,则表示倒数计算的位置。
如果省略第二个参数,则一直返回到原数组的最后一个成员。负数表示倒数第几个。
如果参数值大于数组成员的个数,或者第二个参数小于第一个参数,则返回空数组。
var arr = ['a','b','c','d'];
console.log(arr.slice(1,3)); // ["b", "c"]
console.log(arr.slice(2)); // ["c", "d"]
console.log(arr.slice(-2,-1)); // ["c"]
console.log(arr.slice(2,1)); // []
splice()
splice() 用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素,该方法会改变原数组。
第一个参数是删除的起始位置,如果是负数,就表示从倒数位置开始删除
第二个参数是被删除的元素个数。
如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
如只是单纯地插入元素,splice方法的第二个参数可以设为0。
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
var arr = ['a','b','c','d'];
console.log(arr.splice(1,1)); // ["b"]
console.log(arr); // ["a", "c", "d"]
var arr = ['a','b','c','d'];
console.log(arr.splice(1,1,'f')); // ["b"]
console.log(arr); // ["a", "f", "c", "d"]
var arr = ['a','b','c','d'];
console.log(arr.splice(1,0,'h')); // []
console.log(arr); // ["a", "h", "b", "c", "d"]
sort()
sort() 对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数,表示按照自定义方法进行排序。该函数本身又接受两个参数,表示进行比较的两个元素。如果返回值大于0,表示第一个元素排在第二个元素后面;其他情况下(小于或等于),都是第一个元素排在第二个元素前面。
var arr = ['5','8','9','2'];
console.log(arr.sort()); // ["1", "2", "4", "5"]
var newArr = arr.sort(function(a, b) {
returnb - a;
});
console.log(newArr); // ["5", "4", "2", "1"]
map()
map() 对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组。
接受一个函数作为参数。该函数调用时,map方法会将其传入三个参数,分别是当前成员、当前位置和数组本身
var arr = [1,2,3];
var newArr = arr.map(function(v){
return v - 1;
});
console.log(newArr); // [0, 1, 2]
forEach()
forEach() 遍历数组的所有成员,执行某种操作,参数是一个函数。它接受三个参数,分别是当前位置的值、当前位置的编号和整个数组。
var arr = ['a', 'b'];
arr.forEach(function(value,index){
console.log(index + ':' + value);
});
//
0 : "a"
1 : "b"
filter()
filter() 参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
filter方法的参数函数可以接受三个参数,第一个参数是当前数组成员的值,这是必需的,后两个参数是可选的,分别是当前数组成员的位置和整个数组。
var arr = [1,2,3];
var newArr = arr.filter(function(v){
return (v > 2);
});
console.log(newArr); // [3];
some()、every()
some() 用来判断数组成员是否符合某种条件。接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值。该函数接受三个参数,依次是当前位置的成员、当前位置的序号和整个数组。只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false。
var arr = [1,2,3];
var bool = arr.some(function(v){
return (v == 3);
});
console.log(bool); // true
every() 用来判断数组成员是否符合某种条件。接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值。
该函数接受三个参数,依次是当前位置的成员、当前位置的序号和整个数组。所有数组成员的返回值都是true,才返回true,否则false。
var arr = [1,2,3];
var bool = arr.every(function(v){
return (v == 3);
});
console.log(bool); // false
var bool2 = arr.every(function(v){
return (v > 0);
});
console.log(bool2); // true
some和every方法还可以接受第二个参数,用来绑定函数中的this关键字。
reduce()、reduceRight()
reduce() 依次处理数组的每个成员,最终累计为一个值。从左到右处理(从第一个成员到最后一个成员)
reduceRight() 依次处理数组的每个成员,最终累计为一个值。从右到左(从最后一个成员到第一个成员)
两个方法的第一个参数是一个函数,该函数可接收四个参数:
-
累积变量,默认为数组的第一个成员
-
当前变量,默认为数组的第二个成员
-
当前位置(从0开始)
-
原数组
对 reduce() :
var arr = [1, 2, 3, 4, 5];
var total = arr.reduce(function(x, y){
console.log(x, y)
return x + y;
});
console.log(total);
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15
对 reduceRight() :
var arr = [1, 2, 3, 4, 5];
var total = arr.reduceRight(function(x, y){
console.log(x, y)
return x + y;
});
console.log(total);
// 5 4
// 9 3
// 12 2
// 14 1
// 15
两个方法还可传入第二个参数,表示累积变量的初始值:
indexOf()、lastIndexOf()
indexOf() 返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。可以接受第二个参数,表示搜索的开始位置
lastIndexOf() 返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。可以看作是从最后位置开始搜索。
var arr = ['a', 'b', 'a', 'c'];
console.log(arr.indexOf('a')); // 0
console.log(arr.indexOf('a',1)); // 2
console.log(arr.lastIndexOf('a')); // 2
Date类型
在JavaScript中,Date类型是用来保存日期的,它能精确到1970年1月1日之前或之后的285616年。
创建日期对象
要创建一个日期对象,使用new操作符和Date构造函数即可:
var now = new Date();
在调用Date构造函数而不传递参数时,新创建的对象自动获得当前日期和时间。
如果要根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数(即从UTC时间1970年1月1日起至该日期止经过的毫秒数)
日期/时间组件方法
日期/时间组件方法可分为两类:
-
get类方法:获取Date对象的日期和时间
-
set类方法:设置Date对象的日期和时间
get类方法
Date对象提供了一些获取日期和时间的方法:
getTime()//返回距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法。
getDate()//返回实例对象对应每个月的几号(从1开始)。
getDay()//返回星期几,星期日为0,星期一为1,以此类推。
getYear()//返回距离1900的年数。
getFullYear()//返回四位的年份。
getMonth()//返回月份(0表示1月,11表示12月)。
getHours()//返回小时(0-23)。
getMilliseconds()//返回毫秒(0-999)。
getMinutes()//返回分钟(0-59)。
getSeconds()//返回秒(0-59)。
getTimezoneOffset()//返回当前时间与UTC的时区差异,以分钟表示,返回结果考虑到了夏令时因素。
上面这些方法返回的都是正数,不同值返回的范围不一样:
分钟和秒:0 到 59
小时:0 到 23
星期:0(星期天)到 6(星期六)
日期:1 到 31
月份:0(一月)到 11(十二月)
年份:距离1900年的年数
set类方法
Date对象提供了一些设置日期和时间的方法:
setDate(date)//设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。
setYear(year)://设置距离1900年的年数。
setFullYear(year [, month, date])//设置四位年份。
setHours(hour [, min, sec, ms])//设置小时(0-23)。
setMilliseconds()//设置毫秒(0-999)。
setMinutes(min [, sec, ms])//设置分钟(0-59)。
setMonth(month [, date])//设置月份(0-11)。
setSeconds(sec [, ms])//设置秒(0-59)。
setTime(milliseconds)//设置毫秒时间戳。
RegExp类型
正则表达式(regular expression)是一个描述字符模式的对象。JavaScript的RegExp类表示正则表达式,String和RegExp都定义了方法。
正则表达式的定义
正则表达式有两种方法定义:
-
一种是使用正则表达式直接量,将其包含在一对斜杠(/)之间的字符。
var pattern = /s$/;
-
另一种是使用RegExp()构造函数。
var pattern = new RegExp('s');
上面两种方法是等价的,用来匹配所有以字母“s”结尾的字符串。
正则表达式的模式规则是由一个字符序列组成的,所有字母和数字都是按照字面含义进行匹配的。
直接量字符
avaScript正则表达式语法也支持非字母的字符匹配,这些字符需要通过反斜杠(\)作为前缀进行转义。
有如下直接量字符:
\0 匹配null字符(\u0000)。
[\b] 匹配退格键(\u0008),不要与\b混淆。
\t 匹配制表符tab(\u0009)。
\n 匹配换行键(\u000A)。
\v 匹配垂直制表符(\u000B)。
\f 匹配换页符(\u000C)。
\r 匹配回车键(\u000D)。
\xnn 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
\uxxx 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的unicode字符。
\cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
字符类
将直接量字符单独放进方括号就组成了字符类(character class)。一个字符类可以匹配它所包含的任意字符。比如:/[abc]/就和字母“a”、“b”、“c”中的任意一个都匹配。
我们还可以通过“”符号来定义否定字符类,它匹配所有不包含括号内的字符。定义否定字符类时,将一个“”符号作为左方括号内的第一个字符。比如: /[^abc]/ 匹配的是“a”、“b”、“c”之外的所有字符。
字符类还可以使用连字符来表示字符范围。比如要匹配拉丁字母表中的小写字母,可以使用 /[a-z]/ ,要匹配拉丁字母表中的任何字母和数字,则使用 /[a-zA-Z0-9]/ 。
正则表达式的字符类:
[...] 方括号内的任意字符
[^...]不在方括号内的任意字符
. 除换行符和其他Unicode行终止符之外的任意字符
\w 任何ASCII字符组成的单词,等价于[a-zA-Z0-9]
\W 任何不适ASCII字符组成的单词,等价于[^a-zA-Z0-9]
\s 任何Unicode空白符
\S 任何非Unicode空白符的字符
\d 任何非ASCII数字,等价于[0-9]
\D 除了ASCII数字之外的任何字符,等价于[^0-9]
[\b] 退格直接量
重复
在正则模式之后跟随用以指定字符重复的标记。
正则表达式的重复字符语法:
{n,m} 匹配前一项至少n次,至多m次
{n,} 匹配前一项n次或者更多次,也可以说至少n次
{n} 匹配前一项n次
? 匹配前一项0次或者1次,等价于{0,1}
+ 匹配前一项1次或多次,等价于{1,}
* 匹配前一项0次或多次,等价于{0,}
非贪婪的重复
默认情况下,匹配重复字符是尽可能多的匹配,而且允许后续的正则表达式继续匹配,即匹配直到下一个字符不满足匹配规则为止,这称为“贪婪的”匹配。
当然,我们也可以使用正则表达式进行非贪婪匹配,一旦条件满足,就不再往下匹配。,只须在待匹配的字符后跟随一个问号即可:“??”、“+?”、“*?”或“{1,5}?”。
/a+/.exec('aaa') //["aaa"]
/a+?/.exec('aaa') //["a"]
《半知半解》82-86未看,先略过
基本包装类型(Boolean、Number、String)
ECMAScript提供了三个基本包装类型: Boolean 、 Number 、 String 。
实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能过调用一些方法来操作这些数据。执行步骤如下:
-
创建S提让那个类型的一个实例
-
在实例上调用指定的方法
-
销毁这个实例
var s1 = new String('test');
var s2 = s1.substring(2);
s1 = null;
引用类型与基本包装类型的区别在于对象的生存期:使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中,而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即销毁,这也是我们不能再运行时为基本类型值添加属性和方法的原因。
var s = 'tg';
s.age =10;
console.log(s.age); // undefined
上面代码执行输出的是undefined,这是因为第二行创建的String对象在执行第三行代码时已经被销毁了,第三行又创建自己的String对象,而该对象没有age属性。
Number类型
格式化方法
Number.prototype.toFixed()
toFixed()方法会按照指定的小数位来返回数值的字符串表示(四舍五入)。
var num = 10.005;
console.log(num.toFixed(2)); // "10.01"
Number.prototype.toExponential()
toExponential()方法用于将一个数转为科学计数法形式。
var num = 10;
console.log(num.toExponential()); //1e+1
toExponential()方法的页可以接受一个参数,参数表示小数点后有效数字的位数,范围为0到20,超出这个范围
Number.prototype.toPrecision()
toPrecision()方法可能返回固定大小格式,也可能返回指数格式,具体规则是看哪种格式最合适的。它也接收一个参数,表示数值的所有数字的位数(不包含指数部分)
var num = 99;
console.log(num.toPrecision(1)); // 1e+2
console.log(num.toPrecision(3)); // 99.0
Number.prototype.toPrecision()
toPrecision()方法可能返回固定大小格式,也可能返回指数格式,具体规则是看哪种格式最合适的。它也接收一个参数,表示数值的所有数字的位数(不包含指数部分)
var num = 99;
console.log(num.toPrecision(1)); // 1e+2
console.log(num.toPrecision(3)); // 99.0
String实例对象的属性和方法
trim()
trim() 是ECMAScript 5新增的,用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。
var str = ' hello';
console.log(str.trim()); // "hello"
console对象
console 对象是JavaScript的原生对象,可以将信息输出在控制台。
控制台
打开控制台以后,你可以看到下列不同的面板:
Elements:查看网页的HTML源码和CSS代码。
Resources:查看网页加载的各种资源文件(比如代码文件、字体文件、css文件等),
以及在硬盘上创建的各种内容(比如本地缓存、Cookie、Local Storage等)。
Network:查看网页的HTTP通信情况。
Sources:查看网页加载的所有源码。
Timeline:查看各种网页行为随时间变化的情况。
Profiles:查看网页的性能情况,比如CPU和内存消耗。
Console:用来运行JavaScript命令。
console对象的方法
log()、warn()、info()、error()、debug()
console.log() ,在控制台中打印信息,它会自动在每次输出的结尾,添加换行符,它可以接受任何字符串、数字和JavaScript对象,也可以接受换行符n以及制表符t。
console.log(1); // 1
console.log('hello'); // "hello"
它可以接受多个参数,将它们的结果连接起来输出。
console.log('a', 'b', 1); // a b 1
-
console.info 用于输出提示性信息,会带上一个蓝色图标
-
console.error用于输出错误信息,会在最前面带上红色的叉,表示出错
-
console.warn用于输出警示信息,会在最前面带上黄色三角
-
console.debug用于输出调试信息
console.info(“提醒”);
console.error(“报错了”);
console.warn(“警告”);
console.debug(“调试信息”);
console对象的上面5种方法,如果第一个参数是格式字符串(使用了格式占位符),将依次用后面的参数替换占位符,然后再进行输出。
不过,占位符的种类比较少,只支持下列五种:
字符(%s)
整数(%d或%i)
浮点数(%f)
对象(%o)
CSS格式字符串(%c)
例子:
console.log('%s%s',1,2); // 12
console.log("%c自定义样式","font-size:20px;color:green");
console.log("%c我是%c自定义样式","font-size:20px;color:green","font-weight:bold;color:red");
trace()、clear()
console.trace() 方法显示当前执行的代码在堆栈中的调用路径。
用 console.clear() 清空控制台。
dir()、dirxml()
console.dir 直接将该DOM结点以DOM树的结构进行输出,可以详细查对象的方法发展等等
console.log({name: 'tg', age: 12});
// Object {name: "tg", age: 12}
console.dir({name: 'tg', age: 12});
// Object
name: "tg",
age: 12,
__proto__: Object
console.dirxml 用来显示网页的某个节点(node)所包含的html/xml代码
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
</table>
<script>
var table=document.querySelector("table");
console.dirxml(table);
</script>
//输出:
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
</table>
group()、groupEnd()、groupCollapsed()
console.group
和 console.groupend
这两个方法用于将显示的信息分组。它只在输出大量信息时有用,分在一组的信息,可以用鼠标折叠/展开。
console.group
输出一组信息的开头
console.groupEnd
结束一组输出信息
console.groupCollapsed
方法与 console.group
方法很类似,唯一的区别是该组的内容,在第一次显示时是收起的(collapsed),而不是展开的。
assert()
console.assert
对输入的表达式进行断言,接受两个参数,第一个参数是表达式,第二个参数是字符串。只有表达式为false时,才输出相应的信息到控制台,否则不输出。
var isTrue=true;
console.assert(isTrue,"我是错误");
isTrue=false;
console.assert(isTrue,"我是错误2"); // "我是错误2"
count()
console.count 当你想统计代码被执行的次数,这个方法很有用
function play(){
console.count("执行次数:");
}
play(); // 执行次数:1
play(); // 执行次数:2
play(); // 执行次数:3
time()、timeEnd()
这两个方法用于计时,可以算出一个操作所花费的准确时间。
console.time
计时开始
console.timeEnd
计时结束
console.time("array");
var a=0;
for(var i=0;i<100000;i++){
a += i;
}
console.timeEnd("array"); // array : 6.063ms
profile()、profileEnd()
console.profile 和 console.profileEnd 配合一起使用来查看CPU使用相关信息
打开浏览器的开发者工具,在profile面板中,可以看到这个性能调试器的运行结果。
timeLine()、timeLineEnd()
console.timeLine 和 console.timeLineEnd 配合一起记录一段时间轴
自定义console对象的方法
console对象的所有方法都可以被覆盖,也就是说,我们可以自定义方法。
console['log'] = console['log'].bind(console, '温馨提示');
console.log('自定义方法'); // 温馨提示 自定义方法
DOM
文档对象模型(Document Object Model,DOM)是表示和操作HTML和XML文档内容的基础API。
当网页被加载时,浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。
上图中的每一个方框是文档的一个节点,它表示一个Node对象,而所有节点组成了节点树(DOM树)。
节点有7种类型:
Document:整个文档树的顶层节点
DocumentType:doctype标签(比如<!DOCTYPE html>)
Element:网页的各种HTML标签(比如<body>、<a>等)
Attribute:网页元素的属性(比如class="right")
Text:标签之间或标签包含的文本
Comment:HTML或XML的注释
DocumentFragment:文档的片段
//Document和Element是两个重要的DOM类。
节点之间的关系
在一个节点之上的直接节点是其 父节点 ,在其下一层的直接节点是其 子节点 。在同一层上具有相同父节点的节点是兄弟节点 。在一个节点之下的所有层级的一组节点是其 后代节点 。一个节点的任何父节点、祖父节点和其上层的所有节点是 祖先节点 。
通用的 Document 和 Element 类型与 HTMLDocument 和 HTMLElement 类型之间是有严格区别的。
Document 类型代表一个HTML或XML文档, Element 类型代表该文档中的一个元素。
HTMLDocument 和 HTMLElement 子类只是针对于HTML文档和元素。
选取文档元素
在JavaScript中,有多种方法选取元素。
-
用指定的id属性
-
用指定的name属性
-
用指定的标签名字
-
用指定的CSS类
-
匹配指定的CSS选择器
元素的内容
innerHTML
读取Element的 innerHTML 属性作为字符串标记返回那个元素的内容。
<div id="div"><p>123</p></div>
var d = document.getElementById('div');
d.innerHTML // "<p>123</p>"
除了获取,还可以设置
d.innerHTML = '<span>99</span>'
// <div id="div"><span>99</span></div>
outerHTML
outerHTML属性返回一个字符串,内容为指定元素节点的所有HTML代码,包括它自身和包含的所有子元素。
d.outerHTML
// "<div id="div"><p>123</p></div>"
outerHTML属性是可读写的,当设置元素的outerHTML时,元素本身被新的内容所替换。
注意:只有Element节点有outerHTML属性,Document节点没有。
insertAdjacentHTML()
将任意的HTML标记字符插入到指定的元素“相邻”的位置。
传入两个参数:标记是该方法的第二个参数,并且“相邻”的精确含义依赖于第一个参数的值;第一个参数有以下值之一的字符串:“beforebegin”、“afterbegin”、“beforeend”和“afterend”。如下图:
作为纯文本的元素内容
当要查询纯文本形式的元素内容或在文档中插入纯文本(不必转义HTML标记中使用的尖括号后台&符号)时,我们使用node的textContent属性来实现:
<div id="div"><p>123</p></div>
var d = document.getElementById('div');
d.textContent //123
textContent属性就是将指定元素的所有后代Text节点简单的串联在一起。
textContent是可读写的:
d.textContext = '<span>45</span>';
//<span>45</span>
上面代码在插入文本时,会将 <span> 标签解释为文本,而不会当作标签处理。
DocumentFragment
DocumentFragment(文档片段)是一种特殊的Node,它作为其他节点的一个临时的容器,并不存在于文档中。
var frag = docment.createDocumentFragment();
DocumentFragment是独立的,而不是任何其他文档的一部分。它的parentNode总是为null。但类似Element,它可以有任意多的子节点,也可以使用appendChild()等方法。
DocumentFragment的特殊之处在于它使得一组节点被当做一个节点看待。
盒状模型
元素的位置是以像素来度量的,向右代表X坐标的增加,向下代表Y坐标的增加。
坐标系的原点 :元素的X和Y坐标可以相对于文档的左上角或者相对于其显示文档的视口的左上角。
视口 :实际显示文档内容的浏览器的一部分,不包括浏览器“外壳”(如菜单、工具条和标签页)。
文档 :是基于整个网页。
查询元素的几何尺寸
我们可以调用 getBoundingClientRect() 方法来判定一个元素的尺寸和位置。它不需要参数,返回一个有width、height、left、right、top和bottom属性的对象。
getBoundingClientRect() 方法返回元素在视口坐标中的位置。
getBoundingClientRect 方法返回的rect对象,具有以下属性(全部为只读)。
x//元素左上角相对于视口的横坐标
left//元素左上角相对于视口的横坐标,与x属性相等
right//元素右边界相对于视口的横坐标(等于x加上width)
width//元素宽度(等于right减去left)
y//元素顶部相对于视口的纵坐标
top//元素顶部相对于视口的纵坐标,与y属性相等
bottom//元素底部相对于视口的纵坐标
height//元素高度(等于y加上height)
由于元素相对于视口(viewport)的位置,会随着页面滚动变化,因此表示位置的四个属性值,
都不是固定不变的。如果想得到绝对位置,可以将left属性加上window.scrollX,
top属性加上window.scrollY。注意:getBoundingClientRect方法的所有属性,
都把边框(border属性)算作元素的一部分。也就是说,
都是从边框外缘的各个点来计算。因此,width和height包括了元素本身 + padding + border。
判断元素在某点
elementFromPoint() 方法,传递X和Y坐标(使用视口坐标),该方法返回在指定位置的一个元素。
滚动
Element.scrollLeft 属性表示网页元素的水平滚动条向右侧滚动的像素数量, Element.scrollTop 属性表示网页元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素,这两个属性总是等于0。
如果要查看整张网页的水平的和垂直的滚动距离,要从document.body元素上读取。
document.body.scrollLeft
document.body.scrollTop
这两个属性都可读写,设置该属性的值,会导致浏览器将指定元素自动滚动到相应的位置。
scrollTop()
也可以调用window对象的scrollTop()方法来滚动,接受一个点的X和Y坐标(文档坐标),并作为滚动条的偏移量设置它们。
scrollBy()
用于将网页移动指定距离,单位为像素。它接受两个参数:向右滚动的像素,向下滚动的像素。
scrollIntoView()
该方法保证了元素在视口中可见。在默认情况下,它试图将元素的上边缘放在或尽量接近视口的上边缘。如果只传递false作为参数,它将试图将元素的下边缘放在或尽量靠近视口的下边缘。默认true。类似锚点滚动。
属性
clientWidth、clientHeight
clientHeight 属性返回元素节点可见部分的高度, clientWidth 属性返回元素节点可见部分的宽度。
所谓“可见部分”,指的是不包括溢出(overflow)的大小,只返回该元素在容器中占据的大小,对于有滚动条的元素来说,它们等于滚动条围起来的区域大小。
这两个属性的值不包括滚动条、边框和Margin,只包含内容和它的内边距,单位为像素。
对于整张网页来说,当前可见高度(即视口高度)要从document.documentElement对象上获取,等同于window.innerHeight属性减去水平滚动条的高度。
没有滚动条时,这两个值是相等的;有滚动条时,前者小于后者。
var rootElement = document.documentElement; // 没有水平滚动条时
rootElement.clientHeight === window.innerHeight // true // 没有垂直滚动条时
rootElement.clientWidth === window.innerWidth // true
对于 <i> 、 <code> 和 <span> 这些内联元素,clientWidth和clientHeight总是0
clientLeft、clientTop
clientLeft 属性等于元素节点左边框(left border)的宽度, clientTop 属性等于网页元素顶部边框的宽度,单位为像素。
但是如果元素有滚动条,并且浏览器将这些滚动条放置在左侧或顶部(极少见),这两个属性就包括了滚动条的宽度,但不包括Margin和Padding。
如果元素是内联元素,clientLeft和clientTop属性总是为0。
scrollWidth、scrollHeight
scrollHeight 属性返回某个网页元素的总高度, scrollWidth 属性返回总宽度,也就是元素的内容加上它的内边距再加上任何溢出内容的尺寸。这两个属性是只读属性。
它们返回的是整个元素的高度或宽度,包括由于存在滚动条而不可见的部分。默认情况下,它们包括Padding,但不包括Border和Margin。
scrollLeft、scrollTop
scrollLeft 属性表示网页元素的水平滚动条向右侧滚动的像素数量, scrollTop 属性表示网页元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素,这两个属性总是等于0。
如果要查看整张网页的水平的和垂直的滚动距离,要从document.body元素上读取。
document.body.scrollLeft
document.body.scrollTop
这两个属性都可读写,设置该属性的值,会导致浏览器将指定元素自动滚动到相应的位置。
其他文档特性
document.cookie
用来操作浏览器Cookie
domain
返回当前文档的域名
lastModified
包含文档修改时间的字符串
location
与window对象的location属性引用同一个location对象
referrer
document.referrer属性返回一个字符串,表示当前文档的访问来源,如果是无法获取来源或是用户直接键入网址,而不是从其他网页点击,则返回一个空字符串。
title
文档的 <title> 和 </title> 标签之间的内容,可读写。
URL
文档的URL。只读字符串而不是location对象。该属性值与location.href的初始值相同。
doctype
document对象一般有两个子节点。第一个子节点是document.doctype,它是一个对象,包含了当前文档类型(DocumentType Declaration,简写DTD)信息。对于HTML5文档,该节点就代表<!DOCTYPE html>。如果网页没有声明DTD,该属性返回null。
documentElement
document.documentElement 属性返回当前文档的根节点(root)。它通常是document节点的第二个子节点,紧跟在document.doctype节点后面。
defaultView
document.defaultView 属性,在浏览器中返回document对象所在的window对象,否则返回null。
document.defaultView === window // true
activeElement
document.activeElement属性返回当前文档中获得焦点的那个元素。用户通常可以使用Tab键移动焦点,使用空格键激活焦点。比如,如果焦点在一个链接上,此时按一下空格键,就会跳转到该链接。
characterSet
document.characterSet属性返回渲染当前文档的字符集,比如UTF-8、ISO-8859-1。
readyState
document.readyState属性返回当前文档的状态,共有三种可能的值。
loading:加载HTML代码阶段(尚未完成解析)
interactive:加载外部资源阶段时
complete:加载完成时
查询选取的文本
标准的window.getSelection()方法返回一个Selection对象,后者描述了当前选取的一系列一个或多个Range对象。
可编辑的内容
我们可以设置任何标签的HTML contenteditable属性或者用JavaScript设置对应元素的contenteditable属性,使得元素的内容变成可编辑。
<div contenteditable="true"></div>
当你让标签的内容变成可编辑时,有些浏览器会默认开启检查,如果你不需要时,可以这样设置:
<div contenteditable="true" spellcheck="false"></div>
在当今的一些富文本编辑中,常常使用iframe来当文本框,只需将Document对象的designMode属性设置为字符串“on”就可使得整个文档可编辑(“off”将恢复只读文档)。
<iframe id="editor"></iframe>
var editor = document.getElementById('editor');
editor.contentDocument.designMode = 'on';
由于designMode属性并没有对应的HTML属性,所以要使用contentDocument属性。
BOM
计时器
setTimeout() 和 setInterval() 可以用来注册在指定的时间之后单次或重复调用的函数。两者都是客户端JavaScript中的全局函数,也就是Window对象的方法。
setTimeout()
setTimeout() 方法用来实现一个函数在指定的毫秒数之后运行,返回一个值,这个值可以传递给clearTimeout()用于取消这个函数的执行。
var times = setTimeout(function(){},1000); //1000毫秒后执行
clearTimeout(times); //取消执行
setInterval()
setInterval()方法和setTimeout()一样,只不过这个函数会在指定毫秒数的间隔里重复调用,也返回一个值,这个值传递给clearInterval(),用于取消后续函数的调用。
var times = setInterval(function(){},1000); //每隔1000毫秒调用一次function
clearInterval(times); //取消后续函数执行
文档事件
beforeunload
当浏览器将要跳转到新页面时触发这个事件。如果事件处理程序返回一个字符串,那么它将出现在询问用户是否想离开当前页面的标准对话框中。
window.addEventListener('beforeunload',function(e){
var message = '你确认要离开吗!';
e.returnValue = message;
return message
});
unload
unload事件在窗口关闭或者document对象将要卸载时触发,发生在window、body、frameset等对象上面。
它的触发顺序排在beforeunload、pagehide事件后面。unload事件只在页面没有被浏览器缓存时才会触发,换言之,如果通过按下“前进/后退”导致页面卸载,并不会触发unload事件。
load、error
load 事件直到文档加载完毕时(包括所有图像、JavaScript文件、CSS文件等外部资源)才会触发。
error 事件在页面加载失败时触发。注意,页面从浏览器缓存加载,并不会触发load事件。
这两个事件实际上属于进度事件,不仅发生在document对象,还发生在各种外部资源上面。浏览网页就是一个加载各种资源的过程,图像(image)、样式表(style sheet)、脚本(script)、视频(video)、音频(audio)、Ajax请求(XMLHttpRequest)等等。这些资源和document对象、window对象、XMLHttpRequestUpload对象,都会触发load事件和error事件。
pageshow、pagehide
默认情况下,浏览器会在当前会话(session)缓存页面,当用户点击“前进/后退”按钮时,浏览器就会从缓存中加载页面。
pageshow事件在页面加载时触发,包括第一次加载和从缓存加载两种情况。如果要指定页面每次加载(不管是不是从浏览器缓存)时都运行的代码,可以放在这个事件的监听函数。
pageshow事件有一个persisted属性,返回一个布尔值。页面第一次加载时,这个属性是false;当页面从缓存加载时,这个属性是true。
pagehide事件与pageshow事件类似,当用户通过“前进/后退”按钮,离开当前页面时触发。
pagehide事件的event对象有一个persisted属性,将这个属性设为true,就表示页面要保存在缓存中;设为false,表示网页不保存在缓存中,这时如果设置了unload事件的监听函数,该函数将在pagehide事件后立即运行。
DOMContentLoaded事件、readystatechange事件
DOMContentLoaded 事件:当文档加载解析完毕且所有延迟(deferred)脚本(图片未加载完毕)都执行完毕时会触发,此时图片和异步(async)脚本可能依旧在加载,但是文档已经为操作准备就绪了。也就是说,这个事件,发生在load事件之前。
document.addEventListener('DOMContentLoaded',handler,false);
readystatechange 事件:document.readyState属性会随着文档加载过程而变,而每次状态改变,Document对象上的readystatechange事件都会触发。
document.onreadystatechange = function() {
if(document.readyState == 'complete'){
}
}
scroll事件、resize事件
scroll 事件在文档(window)或文档元素滚动时触发,主要出现在用户拖动滚动条。
resize 事件在改变浏览器窗口大小时触发,发生在window、body、frameset对象上面。
hashchange事件、popstate事件
hashchange事件在URL的hash部分(即#号后面的部分,包括#号)发生变化时触发。如果老式浏览器不支持该属性,可以通过定期检查location.hash属性,模拟该事件。
popstate事件在浏览器的history对象的当前记录发生显式切换时触发。注意,调用history.pushState()或history.replaceState(),并不会触发popstate事件。该事件只在用户在history记录之间显式切换时触发,比如鼠标点击“后退/前进”按钮,或者在脚本中调用history.back()、history.forward()、history.go()时触发。
cut事件、copy事件、paste事件
这三个事件属于文本操作触发的事件。
-
cut事件:在将选中的内容从文档中移除,加入剪贴板后触发。
-
copy事件:在选中的内容加入剪贴板后触发。
-
paste事件:在剪贴板内容被粘贴到文档后触发。
这三个事件都有一个clipboardData只读属性。该属性存放剪贴的数据,是一个DataTransfer对象。
焦点事件
焦点事件发生在Element节点和document对象上。
-
focus事件:Element节点获得焦点后触发,该事件不会冒泡。
-
blur事件:Element节点失去焦点后触发,该事件不会冒泡。
-
focusin事件:Element节点将要获得焦点时触发,发生在focus事件之前。该事件会冒泡。Firefox不支持该事件。
-
focusout事件:Element节点将要失去焦点时触发,发生在blur事件之前。该事件会冒泡。Firefox不支持该事件。这四个事件的事件对象,带有target属性(返回事件的目标节点)和relatedTarget属性(返回一个Element节点)。对于focusin事件,relatedTarget属性表示失去焦点的节点;对于focusout事件,表示将要接受焦点的节点;对于focus和blur事件,该属性返回null。
由于focus和blur事件不会冒泡,只能在捕获阶段触发,所以addEventListener方法的第三个参数需要设为true。
鼠标事件
click
click事件当用户在Element节点、document节点、window对象上,单击鼠标(或者按下回车键)时触发。
“鼠标单击”定义为,用户在同一个位置完成一次mousedown动作和mouseup动作。它们的触发顺序是:mousedown首先触发,mouseup接着触发,click最后触发。
contextmenu
contextmenu事件在一个节点上点击鼠标右键时触发,或者按下“上下文菜单”键时触发。
可以通过下面的方式阻止“上下文菜单”的出现:
document.oncontextmenu=function(){
return false;
}
dblclick
dblclick事件当用户在element、document、window对象上,双击鼠标时触发。该事件会在mousedown、mouseup、click之后触发。
mousedown、mouseup
mouseup事件在释放按下的鼠标键时触发。
mousedown事件在按下鼠标键时触发。
mousemove
mousemove事件当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次代码。
mouseover、mouseenter
mouseover事件和mouseenter事件,都是鼠标进入一个节点时触发。
两者的区别是,mouseenter事件只触发一次,而只要鼠标在节点内部移动,mouseover事件会在子节点上触发多次。
mouseenter事件只触发一次,而只要鼠标在节点内部移动,mouseover事件会在子节点上触发多次。
mouseout、mouseleave
mouseout事件和mouseleave事件,都是鼠标离开一个节点时触发。
除了“mouseenter”和“mouseleave”外的所有鼠标事件都能冒泡。链接和提交按钮上的click事件都有默认操作且能够阻止。可以取消上下文菜单事件来阻止显示上下文菜单。
传递给鼠标事件处理程序的事件对象有clientX和clientY属性,它们指定了鼠标指针相对于包含窗口的坐标。加入窗口的滚动偏移量可以把鼠标位置转换成文档坐标。