javascript权威指南笔记

时间:2023-12-14 19:31:08
最近每天工作之余看下js的细节部分,时间不是很多,所以看的进度也不会太快,写个博客监督自己每天都看下。
以前不知道的细节或者以前知道但是没注意过的地方都会记录下来,所以适合有一定基础的,不适合零基础新手。
---------------------------------------------------------国庆期间 开始--------------------------------------------------------- 
js中所有数字都是浮点数,比如5/2不是2,是2.5,0/0为NaN,如果想实现5/2=2可以采用5>>2=2
"1.23" == 1.23 会将字符串转换为数字
33 + '33' = '3333' 字符串和数字相加,会将数字转换成字符串
object == number|string  PS: new Number(123) == 123 或者 new String('123') == '123' 为true ,其他为false
见未知
字符串连接中,使用join比使用+=要快几十倍,比如: ["abc","def"].join("")
--------------------------------------16.10.10添加 开始----------------------------------
包装对象
var s = "hello"
alert(s.length) => 5
在JS定义中字符串s为原始值,那为什么会有length属性?
因为在JS中,只要引用了字符串s的属性,js就会调用new String(s)来转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个对象就会销毁。
比如:
var s = "123"
s.len = 4;
alert(s.len); => undefined
这是因为第二行创建完临时对象以后,马上就被销毁了。所以第三行自然引用不到。
再看:
var s = "123"
s.length = 4;
alert(s.length); => 3
同样的,因为第二行创建的对象并进行赋值以后,马上就被销毁了,第三行创建的是一个新的对象,所以自然就是3了
同样的数字和布尔值也有Number()和Boolean()方法,但是null和undefined就没有。
见46页3.6
--------------------------------------16.10.10添加 结束----------------------------------

js 字符串,数值和布尔值都是不可变的
如:var s=“hello”
s.toUpperCase();
console.log(s)
输出s为hello而不是HELLO
因为函数返回的是一个新字符串,而本身是不会改变的。
见47页3.7

js类型转换表
见49页上

js中对象永远不相等,即使对象中的所有索引以及属性值都一样也不相等,同样两个单独的数组也是永远不相等
原因:对象为引用类型,对象的比较为引用的比较,当为同一个引用对象时才相同
也就是说
var a ={};
var b=a;
此时a===b为true。 
见47页底部
--------------------------------------16.10.10添加 开始----------------------------------
js中对象的toString/valueOf方法
对象转换到字符串是先toString后valueOf,转换到数字反之 
ps:没看出toString/valueOf方法有什么区别,有待深入了解(除了书本上写了Date的对象,toString返回一段时间字符串,valueOf方法返回时间戳)
var a = {x:1} => [object Object]
var a = ['1',2,'你好'] => "1,2,你好"  在元素之间添加逗号后合并成字符串返回
var a = function() { return 0 } =>  function() { return 0 }  返回赋值的定义
function a() {return 0} => function a() {return 0}  返回定义的字符串
/\d+/g => /\d+/g
见52页
--------------------------------------16.10.10添加 结束----------------------------------
变量作用域不受{}代码块限制,只受函数声明限制,函数体内声明的变量都被“提前”至函数体顶部,也就是说在函数体内任何地方定义的变量都可以在函数体内任意地方使用,只是有可能未赋值(如果使用在声明之前)
见57页3.10.1
附加:
  1. 所有全局变量都是window或Global的属性

  2. 函数声明会被提到范围作用域的顶端

  3. 变量声明被提到范围作用域的顶端

  4. 变量声明比函数声明优先级高,变量声明优于函数声明,如果两者同时存在,后被提升的函数声明会覆盖被提升的变量声明

  5. 变量赋值不会被提升,到执行行代码才开始赋值

1.声明的全局变量和2.未声明直接赋值产生的全局变量的不同之处。
1.不能用delete删除
2.可以用delete删除
见58页3.10.2
因为用户用var声明的变量不能用delete删除
见89页中上

.访问和[]访问的区别
.访问会直接查找.后的属性值
[]访问会计算括号内的表达式并转为字符串后进行访问
这个特点导致如果属性名称是一个保留字(ES3)或者包含空格和标点符号,或是一个数字(对数组来说),则必须使用方括号
见63页底部

运算符相关
见66页

js比较运算符,如果比较的两个操作数,有一个为NaN,那么总是返回false,NaN和任何值都不相等,包括它自己,所以判断x是否为NaN可以用x!==x来判断
见77页上方

eval()作用
1.定义别名后eval就是全局的,此时可以在函数内使用全局变量的值(即使函数内有同名变量)
见85页代码段
2.未知

function定义
1.var funcname = function(){;}函数定义表达式
2.function funcname(){;}函数声明语句
区别:1.同var声明变量一样,只有变量声明被提前到了作用域顶部,但是没有值
2.整体都被提前
见95页底部

52-54需要细看

else if并不是真正的js语句,只不过是多条if/else 语句连在一起时的一种惯用写法
见98页

使用switch的场景
所有分支都依赖同一个表达式的值时,重复计算多条if语句中的表达式非常浪费
见99页上

switch中case后面的表达式与switch后的表达式的值是用“===”进行判断
见99页中

default可以放在switch内任何地方
见101页上

5.5.4
for/in
for(var i in o)

每次会将循环到的o的值赋值给i
所以可以这样
var a = { x:1,y:2}
var an =[];
var i=0;
for(an[i++] in a);
来获取a中的所有属性
见104页

标签语句
类似c语言goto,不常用,使用方法不熟悉
见106页

continue语句在不同循环体中不同的表现行为
while 判断开始的循环表达式
do/while 判断结尾的循环表达式
for 先计算自增表达式,再判断循环表达式
for/in 遍历下一个属性名
见108页5.6.3

throw的向上传递
见110页5.6.5下

finally执行问题
只要try语句中有一部分代码执行了,finally就会执行。就算try中使用了return,continue,break也是如此

利用try/finally使while循环模拟for循环(无法完美实现)
见112页下

with语句
将对象添加到作用域链的头部,不建议使用
见113页5.7.1

debugger
设置程序断点,用于程序调试(作为ACMer)
见114页5.7.2

“use strict”
使用严格模式
严格模式区别(前三条非常重要):
1.禁止使用with语句
2.所有变量都要先声明
3.调用的函数(不是方法)中的this为undefined
4.通过call和apply来调用函数时,this就是传入的第一个参数
其余见115页中
------------------------------------------------国庆期间 结束--------------------------------------------------------------------------- 
------------------------------------------------16.10.11 开始--------------------------------------------------------------------------- 
对象的属性名如果为保留字(ES3)/有空格/有-连字符的话必须用引号引起来
最后一个属性后的逗号将忽略,ES3中大部分实现中也可以,但是在IE中报错。
见120页中下
创建对象的三种方法:
1、var o1 = {};
2、var o2 = new object();
3、var o3 = Object.create(Objecet.prototype);
这三种方法创建出来的对象都是一样的,都是继承自Objecet.prototype。
是不一样的。
其中2和3方法都可以指定原型对象.
var p = {x:1}
var o2 = new object(p);
var o3 = Object.create(p);
见121页6.2.1
------------------------------------------------16.10.11 结束--------------------------------------------------------------------------- 
------------------------------------------------16.10.13 开始--------------------------------------------------------------------------- 
对象的属性的赋值操作会首先检查原型链,如果原型链中有,并且是只读的,那么赋值操作就是不允许的。否则,就在原始对象(不是原型链上的)添加新的属性或者对已有的属性赋值。
在查询属性时才会体会到继承的存在,而设置属性则和继承无关。
见125页下
给对象o设置属性p失败的场景:
1、o中的属性p是只读的。
2、o中的属性p是继承属性,而且是只读的。
3、看不懂,参见6.8.3
见127页中
126页6.2.3的上面有一段看不懂,参见6.6,以后回来再看。
如果o继承了x属性,而x属性恰好是一个存取器属性(参见6.6)那么如果设置o.x=2是不会创建属性的,也不会修改父类的值,只会修改本类的值。
var a ={
  x:1,
  get r(){return this.x},
  set r(value){this.x = value}
}
var b = Object.create(a);
b.r = 2;  //这个操作修改了b中x的值
b.x    //2
a.x    //因为b中的操作只会修改b的值,所以a.x值不会变。
检测属性是否在对象中。
in/ !==:()
属性名 in 对象
var o = {x:1}
"x" in o  //true
o.x !== undefined; //true
"y" in o //false
o.y !== o //false
"toString" in o //true  o继承toString属性
o.toString !== o //true  o继承toString属性
有一种情况in和!==不同,即属性值为undefined的时候,"x" in o 为true o.x !== undefined 为false。
检测属性是否为对象的自有属性(非继承)
hasOwnProperty():
o.hasOwnProperty("x"); //true
o.hasOwnProperty("y"); //false
o.hasOwnProperty("toString") //false  toString是继承属性
检测属性是否为对象的自有属性,并且属性是否为可枚举的
propertyIsEnumerable():
o.propertyIsEnumerable("x"); //true o有一个可枚举的自有属性x
object.prototype.propertyIsEnumerable("toString"); //false:不可枚举
见128页6.4
------------------------------------------------16.10.13 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.15 开始---------------------------------------------------------------------------
枚举属性
for/in循环可以遍历继承来的属性
见130页上
Object.getOwnPropertyNames(o); // 获取对象的所有自有属性。
见132页上
-----------------------------------------------16.10.15 结束---------------------------------------------------------------------------

-----------------------------------------------16.10.16 开始---------------------------------------------------------------------------
getter和setter
和数据属性不同,由getter和setter定义的为存取器属性
var o = {
  x:1,
  get r(){ return this.x},
  set r(value)  { this.x = value},
}
o.r  //1
o.r = 2;
o.r  //2
此时r这个属性是可读可写的,如果我们将set去掉。不管怎么给o.r赋值,o.r的属性一直都是不变的。但是在非严格模式下是不会报错的。同理,去掉get以后就无法获取属性值,o.r的值就为undefined。
见132页6.6
var a= {
  $n = 0  //$符号暗示这个属性是一个私有属性
}
a.n   //undefined
见134页上
属性的特性(API对库开发者来说非常重要)因为:
1、 可以通过这些API给原型对象添加方法,并将它们设置成不可枚举的,这让它们看起来更像内置方法。
2、可以通过这些API给对象定义不能修改或删除的属性,借此“锁定”这个对象。
属性的4个特性(‘属性描述符’对象):
1、数据属性:值(value)、可写性(writable)、可枚举性(enumerable)、可配置性(configurable)
2、存取器属性:读取(get)、写入(set)、可枚举性、可配置性
通过Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符:
Object.getOwnPropertyDescriptor({x:1},"x")  //  返回{value:1, writable:true, enumerable:true, configurable:true}
Object.getOwnPropertyDescriptor(o,"r")  //查询上面定义的o的r属性,返回{get:/*func*/, set:/*func*/, enumerable:true, configurable:true}
如果属性不存在,或者为继承属性,则返回undefined
见134页6.7
设置属性特性:
var o = {}
Object.defineProperty(o,"x",{ value:1,
                writable:true,
                enumerable:false,
                configurable:true});
//给o对象添加一个不可枚举的数据属性x,并赋值为1
Object.keys(o)  //因为o的x属性是不可枚举的,所以返回空数组[]
Object.defineProperty(o,"x",{writable:false});  //将x属性变成只读
o.x = 2  //操作失败,但在非严格模式中不会报错
o.x   //为1
Object.defineProperty(o,"x",{value:2})  //因为属性依然是可配置的,所以可以通过这种方法进行修改
Object.defineProperty(o,"x",{get:function(){return 0;}});  //还可以将x从数据属性改为存取器属性
o.x  //输出0
从上面可以看出来Object.defineProperty()的属性描述符参数对象不需要包含所有的4个特性,如果是新创建的,那么默认的就是false或者undefined。如果是修改的,那么就只修改设置的。
注意:这个方法要么修改已有属性,要么新建自有属性,并不能修改继承属性。
见135页中下
同时修改或创建多个属性:
var o = {};
Object.defineProperties(o,{
  x:{value:1,  writable:true,  enumerable:true,  configurable:true},
  y:{value:2,  writable:true,  enumerable:true,  configurable:true},
  r:{
    get:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},
    enumerable:true,
    configurable:true
  }
});
见136页中
Object.defineProperty()和Object.defineProperties()使用规则:
1、如果对象是不可扩展的(参见6.8.3节),则可以编辑已有的自有属性,但不能给它添加新属性。
2、如果属性是不可配置的,则不能修改它的可配置性和可枚举性。
3、如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性。
4、如果数据属性是不可配置的,则不能将它转换为存取器属性。
5、如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但可以从true修改为false。
6、如果数据属性是不可配置且不可写的,则不能修改它的值。然而可配置但不可写属性的值是可以修改的(实际上是先将它标记为可写的,然后修改它的值,最后转换为不可写的)。
见136页下
检测对象是否是另一个对象的原型:
var p={x:1}
var o = Object.creat(p);
p.isPrototypeOf(o);  //true
Object.prototype.isPrototypeOf(o)  //true
isPrototypeOf()和instanceof运算符非常类似
-----------------------------------------------16.10.16 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.20 开始---------------------------------------------------------------------------
对象的可扩展性:
ES5中所有内置对象和自定义对象都是显式可扩展的,除非将他们转换为不可扩展的。宿主对象的可扩展性是由JS引擎定义的。
Object.esExtensible(o)  //判断o对象是否是可扩展的
Object.preventExtensions(o)   //将o对象转换为不可扩展的,注意,如果转换为不可扩展的,则无法再将其转换为可扩展的。
同时,preventExtensions只会影响到对象本身的可扩展性。如果给一个不可扩展的对象的原型添加属性,这个对象同样会继承这些属性。
Object.seal(o)  //*,将对象设置为不可扩展的,并且将对象所有的自有属性设置为不可配置的。即无法添加,删除或配置。如果是已有的可写属性,则依然可以设置。
Object.isSealed(o)  //判断是否*对象
Object.freeze(o)  //冻结,seal的升级版,会将所有数据属性设置为只读,存取器属性不受限制。
Object.isFreeze(o)  //判断是否冻结对象
见140页6.8.3
序列化对象:
JSON.parse()  //将字符串转换为JSON对象()
JSON.stringify()  //将JSON对象转换为字符串(只能序列化对象可枚举的自有属性)
见141页6.9
6.10对象方法以后看
数组:
数组是一个特殊化的对象。当使用非整数或负数的作为下标的时候,则自动添加下标为属性名,当添加的下标为非负整数时,则自动维护其length属性
var a=[];
a[-1.23] = true;  //创建一个名为'-1.23'的属性
a["100"] = 0;  //这是数组的第101个属性,同时数组的length变为101
a[1.000]  = 0  //和a[1]相等
见146页下
稀疏数组:
按书中的说法,当采用new方法时才会产生稀疏数组,采用直接量的时候就不会,比如:
var a1 = [,,,];
var a2 = new Array(5);
0 in a1   //true
0 in a2  //false
但是实际操作中,两个都是显示的false
然后在下面的操作中又说了:
var a1=[,];
var a2 = [undefined];
0 in a1   //false
0 in a2  //true
见147页下
如果将数组length设置为比数组真实长度小时,数组会删除超出部分的元素。比如:
var a = [1,2,3,4,5];
a.length = 3;  //a=[1,2,3]
因此,如果让一个数组元素不能配置,那么就不能删除它,所以length的值就不能小于这个元素的索引值+1,如果小于,不会报错,但是不会发生改变。
见148页下
a.push(“123”) === a[a.length] = “123” 
用delete删除数组中的元素,不会影响数组的length
见149页7.5

如果数组同时拥有对象属性和数组元素,返回的的属性名很有可能是按照创建的顺序而非数值的大小顺序。所以尽量避免使用for/in循环数组(虽然我的测试是先循环数组,再循环属性)
见151页上
-----------------------------------------------16.10.20 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.21 开始---------------------------------------------------------------------------
JS不支持真正的多维数组,但可以用数组的数组来近似。
见151页7.7
数组方法:见152页7.8或者本博客的JAVASCRIPT笔记
sort()方法
var a = [1,3,2,4,6,5]
a.sort()  //当不带参数时,ASCII码顺序排列。
a.sort(function(a,b){return b-a})  //带参数的sort,参数为一个函数,规定了排列的顺序,如果a要排在b前面,则返回小于0的数,如果b要在a之前,则返回大于0的数,如果无所谓,返回0,这个例子返回从大到小排列的数组
ES5中的数组方法:
forEach()  //将数组按照索引的顺序按个传递给定义的一个函数。
var data=[1,2,3,4,5];
var sunOfSquares = 0;
data.forEach(function(x){
  sumOfSquares +=x*x;
});
data.forEach(function(v,i,a){a[i] = v+1}  //可以使用三个参数,分别为元素,索引和数组本身
注意:forEach循环无法使用break提前终止语句,如果需要提前终止,必须放在try块中,并能抛出一个异常。比如:
function foreach(a,f,t){
  try{a.forEach(f,t);}
  catch(e){
    if(e === foreach.break) return;
    else throw e;
  }
}
foreach.break = new Error("stopIteration");
map()
a = [1,2,3];
b = a.map(function(x){return x*x});   //b为[1,4,9],与forEavh不同的是,map有返回值,返回一个新的数组。它不修改调用的数组。
filter()
filter()返回的数组元素是调用的数组的一个子集。传递的函数是用来逻辑判定的:该函数返回true或false。来决定该元素是否属于这个子集。
a = [5,4,3,2,1];
b = a.filter(function (x) {return x<3});  //[2,1]
c = a.filter(function(x,i) {return i%2 == 0});  //[5,3,1];
注意:filter()会跳过数组中缺少的元素,他的返回数组总是稠密的。
所以我们可以这样:a = a.filter(function() {return true;})来使数组变为稠密数组
甚至,压缩空缺并删除undefined和null元素,可以这样使用filter();
a = a.filter(function(x) {return x !== undefined && x != null});
every()和some()
这两个函数是对数组中的每个元素进行逻辑判定,返回true或false、
every()相当于数学中的所有量词,比如:
a = [1,2,3,4,5]
a.every(function(x){return x<10};)  //true,数组中所有元素<10
a.every(function(x){return x%2 === 0;})  //false,数组中并不是所有元素都为偶数
some()则相对,比如:
a.some(function(x){return x%2 === 0;})  //true,数组中有偶数值
a.some(isNaN)  //false,数组中不包含非数值元素
需要注意的时,这两个函数一旦确定需要返回什么样的值就会停止遍历元素,如同复合的if条件一样
reduce()和reduceRight()
不知道怎么描述这个函数。直接看例子吧
var a = [1,2,3,4,5];
var sum = a.reduce(function(x,y){return x+y},0);  //数组求和
var product = a.reduce(function(x,y){return x*y},1);  //数组求积
var max = a.reduce(function(x,y){return (x>y)?x:y;});  //求最大值
如上所示,reduce函数需要两个参数,第一个是函数,函数会返回一个计算后的值,第二个是初始值。函数中第一个参数是到目前为止的操作累积结果,第2-4个参数为v,i,a三兄弟。
在第一次调用的时候,初始值就为函数的第一个参数,第二次的时候就是函数返回的值为第一个参数,以此类推。
如果不传递第二个参数,则函数会选择数组的第一个元素为第一参数,第二个元素作为第二参数,所以上面的例子中其实是可以省略第二个参数的。但是在空数组上,不带初始值参数调用reduce()会导致类型错误异常。如果只有一个值,或者空数组带一个初始值,则只会返回那个数,并不会执行函数,比如:
a = [];
a.reduce(function(x,y){return x*2},2);  //返回2,并没有执行*2操作
reduceRight()和reduce()的区别就是reduceRight是从高到低执行
indexOf()和lastIndexOf()
获取数组中给定元素的索引,没有则返回-1
a = [6,1,4,3,1];
a.indexOf(1); //1
a.lastIndexOf(1); //4
a.indexOf(1,3)  //4,第二个参数为指定起始位置
见156页7.9
-----------------------------------------------16.10.21 结束---------------------------------------------------------------------------

-----------------------------------------------16.10.22 开始---------------------------------------------------------------------------
this:
嵌套函数作为函数调用时,this值指向全局对象(非严格模式下)或者为undefined(严格模式下)。
比如:
var o={
  m:function(){
    var self = this;
    console.log(this === o)   //true
    f();
    function f(){
      console.log(this===o)  //false
      console.log(self === o) //true  
    }
  }
}
见171页下
构造函数:
如果没有形参,则可以省略()
var o = new Object();
var o = new Object;
这两行代码是一模一样的。
-----------------------------------------------16.10.22 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.23 开始---------------------------------------------------------------------------
实参对象:arguments
arguments实际上并不是真正的数组,它是一个实参对象。只是碰巧具有以数字为索引的属性。
arguments还有callee和caller两个属性
callee:指代当前正在执行的函数
caller:指代当前正在执行的函数的函数
见175页

自定义函数属性:
function factorial(n){
  if(isFinite(n) && n > 0 && n == Math.round(n)){
    if(!(n in factorial))
      factorial[n] = n * factorial(n-1);
    return factorial[n];  
  }
  else return NaN;
}
factorial[1] = 1;
这个函数使用自身的属性,来缓存了每一次计算的结果。
见180页
闭包
可以让函数外部访问到函数内部的变量。
初看很强大,之前也是这个部分很难理解,现在一路看下来要好很多了,具体的,明天静下心来好好看。
见182页8.6
-----------------------------------------------16.10.23 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.24 开始---------------------------------------------------------------------------
 看半天闭包看不明白,花了时间把这个博客看完了,讲的很赞,容易懂,点击这里
但是很遗憾文章里面没有讲到,倒是书上讲到了一个内容,就是多个闭包时,变量的共享:
function constfuncs(){
  var funcs = [];
  for(var i = 0; i < 10; i++)
    funcs[i] = function(){return i};
  return funcs;
}
var funcs = constfuncs();
funcs[5]()  //返回10
这是因为关联到闭包的作用于链都是“活动的”
见187页下
-----------------------------------------------16.10.24 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.25 开始---------------------------------------------------------------------------
call()和apply()区别
apply()传入实参后,剩下的参数都以数组的形式传递,可以使用类数组对象,也可以将当前的函数的arguments数组直接传入apply()来调用另一个函数
见190页中
这节有点难度,不是很好理解,明天重新看一遍
-----------------------------------------------16.10.25 结束---------------------------------------------------------------------------
 -----------------------------------------------16.10.26 开始---------------------------------------------------------------------------
bind()方法:
f().bind(o),并传入一个对象o作为参数,这个方法将返回新的函数。
也可以传入n个参数,将第2-n个参数作为f()的参数再传给f()
用bind()返回的函数做构造函数的那部分看不懂
见192页中
Function构造函数
可以动态的创建并编译函数,比如放在if中
见193页中
函数式编程
参数是函数,返回的也是函数。
代码看起来很优雅,把一个函数拆分成了很多个小的函数,感觉封装思想很好。但是确实绕来绕去的。
考虑到工作中主要是进行DOM和BOM操作,所以从明天开始看第二部分的客户端JS
-----------------------------------------------16.10.26 结束---------------------------------------------------------------------------

 -----------------------------------------------16.11.02 开始---------------------------------------------------------------------------
343页中说,document对象有一个URL属性,Location对象也表示的为该窗口中当前显示的文档的URL,但是如果定位到文档中的片段标识符(如#top),location对象会做相应的更改,而document.URL属性却不会改变。(书中原文)但实际上,在chrome中测试的时候发现,ducoment.URL属性是也会改变的。
location.assign("http://www.baidu.com")和location.href="http://www.baidu.com"看上去是一样的  //在当前页面到基础上载入新的文档,如果在新的文档按返回键,则会返回当前页面
location.replace("http://www.baidu.com")  //载入新的文档,如果在新的文档按返回键,则会返回首页
见344页14.2.2
现在有了ajax技术后,我们很多情况下都会使用无刷新的方式来进行文档载入,那么就会存在一个问题,就是这个无刷新的过程中url是不会改变的,那么如果实现前进和后退功能呢,这个时候我们可以在使用了ajax技术的地方采用a标签锚点方式。比如<a href="#page_1">第一页</a> 因为浏览器会读取这个锚点信息,所以url会进行改变,url改变了,那么自然这个网页就进入到了历史纪录中了。就可以采用前进后退到方式进行浏览了。
 -----------------------------------------------16.11.02 结束---------------------------------------------------------------------------

 -----------------------------------------------16.11.03 开始---------------------------------------------------------------------------
navigator对象
属性:
appName  除了IE为"Microsoft Internet Explorer",其它浏览器通常为了兼容取值为"Netscape"
appVersion  此属性通常以数字开始,并包含浏览器厂商和版本信息的详细字符串。没有标准的格式,所以没有办法直接用它来判断浏览器类型。
userAgent  浏览器在它的USER-AGENT HTTP头部中发送的字符串。这个属性通常包含appVersion中的所有信息。并且常常也可能包含其它细节。由于这个属性包涵绝大部分信息,因此浏览器嗅探代码通常用它来嗅探
platform   在其上运行浏览器的操作系统(并且可能是硬件)的字符串。
onLine  表示浏览器当前是否连接到网络
geolocation   定义用于确定用户地理位置信息的借接口。
javaEnabled()  一个非标准的方法,当浏览器可以运行java小程序时返回true。
cookieEnable()  非标准的方法,如果浏览器可以永久保存的cookie时,返回true。当cookie配置为“视具体情况而定”时可能会返回不正确的值。
screen对象
width和height  以像素为单位的窗口大小
availWidth和availHeight  实际可用的显示大小
见346页14.4.1
 -----------------------------------------------16.11.03 结束---------------------------------------------------------------------------

 -----------------------------------------------16.11.17 开始---------------------------------------------------------------------------
作为window对象属性的文档元素
如果一个dom元素用id属性来为元素命名,并且如果window对象没有此名称的属性(包括全局变量,因为全局变量也是挂载在window的属性上的),那么window对象就会将这个id作为自己的属性,用来表示对应的dom元素。(非常惊奇,原来还可以这样)
以下HTML元素如果有name属性的话,也会这样表现:
a applet area embed form frame frameset iframe img object
因为name不是唯一的,所以如果有多个相同的name属性,具有该名称的隐式全局变量会引用一个类数对象,这个类数组对象的元素是所有命名的元素。
见352页

 -----------------------------------------------16.11.17 结束---------------------------------------------------------------------------
 -----------------------------------------------16.11.19 结束---------------------------------------------------------------------------
接触到新名词HTMLCollection对象,如:document.images和document.forms。
像getElementsByClassName()返回的为NodeList对象。
HTMLCollection对象为只读的类数组对象。
见367页方框
node对象的属性
document对象,它Element对象和文档中表示文本的Text对象都是node对象。
parentNode   节点的父节点
childNodes    节点的子节点(NodeList对象)
firstChild       第一个子节点
lastChild     最后一个子节点
nextSibling   下一个兄弟节点
previousSibling 上一个兄弟节点
nodeType    节点类型,数字表示
nodeValue     Text或者Comment节点(即注释)的文本内容
nodeName    元素的标签名,全大写。
下面的属性忽略Text和Comment节点,只考虑element节点,除IE之外
firstElementChild
lastElementChild
nextElementSibling
previousElementSibling
childElementCount
 -----------------------------------------------16.11.19 结束---------------------------------------------------------------------------
 -----------------------------------------------16.11.21 开始---------------------------------------------------------------------------

有些HTML属性在js中是保留字。对于这些属性,一般的规则是为属性名加'html'例如,HTML中label的for属性就变成了‘htmlFor’,
但是class是个例外,在js中为className。
见376页中上部。
Node类型定义了attributes属性。对于element对象,attributes属性是只读的类数组对象,它代表元素的所有属性。并且还可以用属性名索引:
document.body.attributes[0]   //body元素的第一个属性
document.body.attributes.bgcolor  //元素的bgcolor属性
document.body.attributes["ONLOAD"]   //元素的onload属性
见378页15.4.4
通常设置innerHTML效率非常高,但是对innerHTML使用+= 通常效率低下,因为它既要序列化又要解析
outerHTML属性,包括了innerHTML以及元素本身。
见379页中部
 -----------------------------------------------16.11.21 结束---------------------------------------------------------------------------
---------------------------------------------相关函数-----------------------------------------------------
Object.create(o)  //创建对象,o为原型对象  121页6.2.1
o.hasOwnProperty("x")  //判断属性x是否为o的自有属性(非继承)  128页6.4
o.propertyIsEnumerable("x")  //判断属性是否为o的自有属性,并且可以枚举  128页6.4
Object.keys(o)  //返回一个由o对象中可枚举的自有属性的名称组成的数组。  132页上
Object.getOwnPropertyNames(o)  //返回o对象的所有自有属性的名称。  132页上
Object.getOwnPropertyDescriptor(o,"r")  //查询o对象的r属性的属性描述符对象
Object.defineProperty(o,"x",{ value:1,
                writable:true,
                enumerable:false,
                configurable:true});
 //给o对象设置x属性,并对x属性添加属性描述符
Object.defineProperties(o,{
  x:{value:1,  writable:true,  enumerable:true,  configurable:true},
  y:{value:2,  writable:true,  enumerable:true,  configurable:true},
  r:{
    get:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},
    enumerable:true,
    configurable:true
  }
});
//给o对象设置多个属性值,并对每个属性值添加属性描述符
Object.esExtensible(o)  //判断o对象是否是可扩展的
Object.preventExtensions(o)   //将o对象转换为不可扩展的,注意,如果转换为不可扩展的,则无法再将其转换为可扩展的。
Object.seal(o)  //*,将对象设置为不可扩展的,并且将对象所有的自有属性设置为不可配置的。即无法添加,删除或配置。如果是已有的可写属性,则依然可以设置。
Object.isSealed(o)  //判断是否*对象
Object.freeze(o)  //冻结,seal的升级版,会将所有数据属性设置为只读,存取器属性不受限制。
Object.isFreeze(o)  //判断是否冻结对象
JSON.parse()  //将字符串转换为JSON对象
JSON.stringify()  //将JSON对象转换为字符串(只能序列化对象可枚举的自有属性)
forEach()  //将数组按照索引的顺序按个传递给定义的一个函数。