《javascript高级程序设计》阅读笔记

parseInt()

按二进制解析var num1 = parseInt("10",2) //2
按十进制解析var num2 = parseInt("10",10) //10
不指定基数意味着让 parseInt 决定如何解析字符串

parseFloat() 与 parseInt() 的区别在于 parseFloat 始终都会忽略前导的零,而且只解析十进制的值


toString()

var num=10;

num.toString();//默认以十进制为基数"10"
num.toString(2);//以二进制为基数"1010"
num.toString(8);//以八进制为基数 "12"
num.toString(16);//以十六进制为基数 "a"

所有的对象都具有 toLocaleString()toString()valueOf() 方法,

栈数据结构 LIFO (last - in - first - Out)后进先出

队列数据结构 FIFO (first - in - first- Out)先进先出

toFixed()

表示保留几位小数,并自动四舍五入。

var num = 10;

num.toFixed(2);//10.00

num.toFixed(4);//10.0000

toExponential()

表示返回以指数表示法(也称e表示法)

var num = 10;
num.toExponential(1);//1.0e+1

toPrecision()

该方法可能会返回固定大小的格式,也可能返回指数格式,具体规则看哪种格式最合适。
var num = 99;
num.toPrecision(1);//1e+2
num.toPrecision(2);//99
num.toPrecision(3);//99.0

toFixed()toExponential()toPrecision()方法可以表示带有0到20个小数位的数值,但这只是标准实现范围,有些浏览器也可能支持更多位数。

数组的常用方法

push()
shift()
unshift()
pop()
join()

sort()方法默认按照升序排列数组项,即最小的值位于最前面,最大的值排在最后面,为了实现排序,sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,即使数组中的每一项都是数值,sort()方法比较的也是字符串。

every()对数组中的每一项运行给定函数,如果该函数的每一项都返回true,则返回true。

filter()对数组中的每一项运行给指定函数,返回该函数返回true的项组成数组。

forEach()对数组中的每一项运行给指定函数,这个方法没有返回。

map()对数组中的每一项运行给指定函数,返回每次函数调用的结果组成的数组。

`some()``对数组中的每一项运行给指定函数,如果该函数中任意一项返回true,则返回true。


ES5新增了两个缩小数组的方法,两个方法都会迭代数组的所有项,

reduce()reduceRight() 都接收四个参数,前一个值、当前值、项的索引、数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。

实现如下:

  1. var calues = [1,2,3,4,5];
  2. var sum = values.reduce(function(prev,cur,index,array){
  3. return prev + cur;
  4. });
  5. console.info(sum); //15

String类型

String对象的方法继承valueOf()toLocaleString()toString()方法,都返回对象所表示的基本字符串值。

两个用于访问字符串中特定字符的方法charAt()charCodeAt()
charAt()
方法以单字符串的形式返回给定位置的那个字符,如下:

var t = "hello word";
t.charAt(1);//e

charCodeAt()
charCodeAt方法返回的是字符编码而不是字符。

var t = "hello word";
t.charAt(1);//101

在ES5中还定义了另一个访问别的字符的方法如下:
var t = "hello word";
stringValue[1];//e

字符串常用方法

concat(a,b,c,…n)
用于合并字符串,更多的时候使用+更加方便。

slice()
str.slice(beginSlice[, endSlice])
slice() 从一个字符串中提取字符串并返回新字符串。在一个字符串中的改变不会影响另一个字符串。也就是说,slice 不修改原字符串,只会返回一个包含了原字符串中部分字符的新字符串。

substr()
str.substr(start[, length])
substr() 方法返回一个字符串中从指定位置开始到指定字符数的字符。

substring()
str.substring(indexStart[, indexEnd])
substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集

以上slice()、substr()、substring()三个方法的区别,如下:
var s = "hello word";
s.slice(-3);//rld
s.substring(-3);//hello world
s.substr(-3);//rld
s.slice(3,-4);//lo w
s.substring(3,-4);//hel
s.substr(3,-4);// //空字符串

indexOf()和lastIndexOf()

这两个方法都是从一个字符串中搜索给定的子字符串,然后返回字符串的位置(如果没有找到字符串则返回-1),两者的区别在于,indexOf()方法从字符串的开头向后搜索,而lastIndexOf()则是从字符串末尾向前搜索。

这两个方法都可以接收第二个参数,表示字符串从哪个位置开始搜索,indexOf()会从指定的位置向后搜索,而lastIndexOf()则会从指定的位置向前搜索。

trim()

ES5中为所有字符串定义了该方法,这个方法传建一个字符串的副本,删除前置以及后缀的所有空格,然后返回结果。
由于trim()返回的是字符串的副本,所以元是字符串中的前置及后缀空格会保持不变。

字符串大小写转换方法

toLowerCase()
toUpperCase()

toLowerCase转换为小写
toUpperCase转换为大写

toLocaleLowerCase()
toLocaleUpperCase()

这两个方法是针对特定的地区实现,如一些少数语言会为Unicode大小写转换应用特殊的规则

split()

fromCharCode
String构造函数本身还有一个静态的方法,这个方法的任务是接受一个或多个字符串编码,然后将他们转换成一个字符串,从本质上来看这个方法与实例方法charCodeAt()执行的是相反的操作,如下:
String.fromCharCode(104,101,108,108,111);//hello

eval()
eval()大概是整个ECMAScript语言中最强大的一个方法。只接收一个参数,
当解析器发现代码中调用eval()方法时,它会将传入的参数当做实际的ECMAScript语句来解析,然后把执行结果插入到原始位置,通过eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该环境想通作用域链,这意味着通过eval()执行的代码可以引用在包含环境中定义的变量,例:
var msg = "hello world";
eval("alert(msg)"); //hello world

注:在eval()中创建的任何函数或变量都不会被提升,因为在解析的时候,他们被包含在一个字符串中。它们只在eval()创建的时候创建。
严格模式下,在外部访问不到eval()中的任何变量或函数。

eval()该功能能力非常强大,同时也非常危险,即在用户输入的时候可能而已输入威胁程序安全的代码,即(代码注入)。

Math对象的属性

Math对象包含的属性大都是数学计算中可能会用到的一下特殊值

Math.E()
自然对数的底数,即常量e的值。

Math.LN10()
10的自然对数

Math.LN2()
2的自然对数

Math.LOG2E()
以2为底e的对数

Math.LOG10E()
以10为底e的对数

Math.PI()
π的值

Math.SQRT1_2
1/2的平方根

Math.SQRT2
2的平方根

min()和max()方法
用于确定一组数值中的最小值和最大值,例如:
var max = Math.max(3,54,32,16); //54
也可以像下面这样使用:

  1. var values = [1,2,3,4,5,6,7,8,];
  2. var max = Math.max.apply(values);//8

舍入法Math.ceil()、Math.floor()和Math.round()

  • Math.ceil()执行向上舍入,即它总是将数组值向上舍入为最接近的整数。
  • Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数。
  • Math.round()执行标准的舍入(四舍五入),

Math.random()生成随机数

Math.random()方法返回一个介于0和1之间的随机数,不包括0和1,。

属性类型(数据属性、访问器属性)

数据属性
数据属性有四个描述其行为的特性。

  • [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,这个特性默认为true
  • [[Enumerable]]:表示能否通过for-in循环返回属性,像前面那样直接在对象上定义属性,它们的这个特性默认值为true
  • [[Writable]]:表示能否修改属性值,这个属性默认为true
  • [[Value]]:包含这个属性的数据值,这个特性默认为undefined

要修改属性的默认特性必须使用到ES5的Object.defineProperty()这个方法,这个方法接收三个参数,属性所在的对象、属性的名称、描述符对象。其中描述符对象必须是configurableenumerablewritablevalue,设置其中一个或多个值。例如:

  1. var p = { };
  2. Object.defineProperty(p,"name",{
  3. writable:false,
  4. value:"hello world"
  5. });
  6. console.log(p.name);//"hello world"
  7. p.name = "nihao";
  8. console.log(p.name);//"hello world"

我们可以多次调用defineProperty属性来修改同一个属性。

[[get]]在读取属性时调用的函数,默认值为undefined。

[[set]]在写入属性时调用函数,默认值为undefined。

  1. var book = {
  2. _year = 2004,
  3. edition = 1
  4. };
  5. Object.defineProperty(book,"year",{
  6. get:function(){
  7. return this._year;
  8. },
  9. set:function(newvalue){
  10. if(newvalue > 2004){
  11. this._year = newvalue;
  12. this.edition +=newvalue - 2004;
  13. }
  14. }
  15. })

在不支持Object.defineProperty()这个方法的浏览器中,可以使用__defineGetter__()__defineSetter__

  1. var book ={
  2. _year:2004,
  3. edition:1
  4. };
  5. book.__defineGetter__("year",function () {
  6. return this._year;
  7. })
  8. book.__defineSetter__("year",function(newvalue){
  9. if(newvalue>2004){
  10. this._year = newvalue;
  11. this.edition += newvalue - 2004;
  12. }
  13. });
  14. book.year = 2005;
  15. alert(book.edition);//2

_year前面的下划线是一种常用的记号,用于表示只能通过方法访问的属性。

ES5也定义了Object.defineProperties()方法,利用这个方法可以一次性描述多个属性.
ES5的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符,这个方法接受两个参数:属性所在的对象和要读取其描述符的属性名称。返回一个对象。该方法可以正对任何对象包括DOM和BOM。

按照惯例,构造函数的首字母应该大写,而非构造函数则以一个小写字母开头。

函数表达式

  • 函数声明,如下:
    1. function a(){
    2. alert("a");
    3. }
  • 函数表达式,如下:
    1. var a = function(){
    2. alert("a");
    3. }

    函数声明会提升函数名,可以在函数声明之前调用,而函数表达式不能再函数声明之前调用。从而理解函数提升。

递归

递归函数是在一个函数通过名字调用自身的情况下构成的。

  1. function SuperType(){
  2. this.property = true;
  3. };
  4. SuperType.prototype.getAvalue = function(){
  5. return this.property;
  6. }
  7. function SubType(){
  8. this.Bproperty = false;
  9. };
  10. //继承了Afun
  11. SubType.prototype = new SuperType();
  12. //使用字面量添加新方法,会导致上一行代码无效。
  13. SubType.prototype = {
  14. getVal:function(){
  15. return this.Bproperty;
  16. },
  17. other:function(){
  18. return false;
  19. }
  20. };
  21. var instance = new SubType();
  22. instance.getAvalue();//error!

hasOwnProperty()方法用来判断该实例的属性是不是存在于实例对象中,而不是继承原型链而来。如下:

  1. function per(){
  2. };
  3. per.name = "yantu";
  4. per.age = 24;
  5. var per1 = new per(),
  6. per2 = new per();
  7. per1.hasOwnProperty("name"); //false//该属性不是来自于实力本身,而是来自于原型链上。

isPrototypeOf()方法用来判断该实例对象是不是继承的另一个对象的原型链而来。如下:

  1. function per(){
  2. };
  3. per.name = "yantu";
  4. per.age = 24;
  5. var per1 = new per(),
  6. per2 = new per();
  7. per.prototype.isPrototypeOf(per1); //true

getPrototypeOf()方法可以方便的取得一个对象的原型。如下:

  1. function per(){
  2. };
  3. per.name = "yantu";
  4. per.age = 24;
  5. var per1 = new per(),
  6. per2 = new per();
  7. Object.getPrototypeOf(per1) == per.prototype; //true

Object.getOwnPropertyDescriptor()方法只能用于实例属性,要取得原型属性的描述符,必须直接在原型对象上调用。

以上代码展示了SuperType的实例赋值给原型,紧接着又将原型替换成一个对象字面量而导致问题,由于现在的原型包含的是一个Object的实例,而非SuperType的实例,因此我们设想中的原型链已经被切断——SubType和SuperType之间已经没有关系,

组合使用构造函数模式和原型模式

创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式,构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享属性。

如果在已经创建的实例的情况下重写原型,那么就会切断现有实例与原型之间的联系。

  • 理解原型对象
  • 原型与in操作符
  • 更简单的原型语法
  • 圆形的动态性
  • 原生对象的原型
  • 原型对象的问题
    • 组合使用构造函数模式和原型模式
    • 动态原型模式
    • 寄生构造函数模式
    • 稳妥构造函数模式

继承

重写原型链示例:
  1. function SuperType(){
  2. this.property = true;
  3. };
  4. SuperType.prototype.getAvalue = function(){
  5. return this.property;
  6. }
  7. function SubType(){
  8. this.Bproperty = false;
  9. };
  10. //继承了Afun
  11. SubType.prototype = new SuperType();
  12. //使用字面量添加新方法,会导致上一行代码无效。
  13. SubType.prototype = {
  14. getVal:function(){
  15. return this.Bproperty;
  16. },
  17. other:function(){
  18. return false;
  19. }
  20. };
  21. var instance = new SubType();
  22. instance.getAvalue();//error!

以上代码展示了SuperType的实例赋值给原型,紧接着又将原型替换成一个对象字面量而导致问题,由于现在的原型包含的是一个Object的实例,而非SuperType的实例,因此我们设想中的原型链已经被切断——SubType和SuperType之间已经没有关系

闭包

闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存,过度使用闭包可能会导致内存占用过多。

关于this对象

在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象,不过,匿名函数的执行环境具有全局性,因此其this对象通常只想window。

例如:

  1. var name = "the window";
  2. var object = {
  3. name = "my object";
  4. getnamefunc:function(){
  5. return function(){
  6. return this.name;
  7. }
  8. }
  9. };
  10. alert(object.getnamefunc());//"the window"(在非严格模式下)

每个函数在被调用时,其活动对象都会自动取得两个特殊标量,this和arguments,内部函数在搜索这两个变量时,只会搜索到其活动对象为止。因此永远不可能直接访问外部函数中的这两个变量。

静态私有变量

初始化一个未经声明的变量,总是会创建一个全局变量。

小结

  • 函数表达式不同于函数声明。函数声明要求有名字,但是函数表达式不需要。没有名字的函数表达式也叫做匿名函数。
  • 在无法确定如何引用函数的情况下,递归函数就会变得比较复杂。
  • 递归应该始终使用arguments.callee来递归地调用自身,不需要使用函数名——函数名可能会发生变化。
  • 在后台执行环境中,闭包的作用域包含着他自己的作用域、包含函数的作用域和全局作用域。
  • 通常函数的作用域及其所有变量都会在函数执行结束后被销毁。
  • 但是函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。
  • 创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用。
  • 结果就是函数内部的所有变量都会被立即销毁,除非将某些变量赋值给了包含作用域(外部作用域)中的变量。
  • 即使javascript 中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量。
  • 有权访问私有变量的公有方法叫特权方法
  • 可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强的模块模式来实现单里的特权方法。

BOM

  1. 定义全局变量与在window对象上直接定义属性还是有一点差别的,全局变量不能通过delete操作符来删除,而直接在window对象上的定义的属性可以。
  2. 尝试访问未声明的变量会跑出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。

窗口关系及框架

如果一个页面包含框架,则每个页面都拥有自己的window对象,并且保存在frames集合中,可以通过数值索引或者框架名称来访问相信的window对象。每一个window对象都有一个name属性,如下:

以上代码创建了一个框架集,其中一个框架居上,两个框架居下,你可以通过window.frames[0]或者window.frames["topFrame"]来引用上方的框架,不过最好使用top而非window来访问,如:top.frames[0]

  • screenLeftscreenTop中保存的是从屏幕左边和上边到由window对象表示的页面可见区域的距离。
  • screenYscreenX中保存的是整个浏览器窗口相对于屏幕的坐标值。
  • moveTomoveBy方法有可能将窗口精确的移动到一个新位置,这两个方法都接收两个参数,其中moveTo接收的是新位置的X、Y坐标,moveBy接收的是在水平和垂直方向上移动的距离。
  • outerWidthouterHeight返回浏览器窗口本身的尺寸,(无论是从最外层的window对象还是从某个框架访问)。
  • innerWidthinnerHeight表示该容器中页面视图区域大小(减去边框宽度)。
  • resizeToresizeBy方法可以调整浏览器窗口大小,这两个方法接收两个参数,其中resizeTo()接收浏览器窗口的新宽度和新高度,而resizeBy()接收新窗口与原窗口的宽度和高度只差。(需要注意的是,这两个方法与移动窗口类型的方法相似,也有可能被浏览器禁用)。

导航和打开窗口

使用window.open()方法可以导航到一个特定的窗口,也可以打开一个新的浏览器窗口。这个方法接收四个参数:要加载的URL、窗口目标、一个特性字符串、一个表示新页面是否取代浏览器历史记录中当前加载页的布尔值。

有些浏览器会在独立的进程中运行每个标签页(如IE8和Chrome),当一个标签页打开另一个标签时,如果两个
window对象之间需要彼此通信,那么新标签页就不能运行在独立的进程中,在Chrome中,将新创建的标签页的opener属性设置为null,即表示在单独的进程中运行新标签页。标签页之间的联系一旦切断,将没有办法恢复。

安全限制

间歇调用和超时调用

setTimeout()是指超时调用,停止:clearTimeout()
setInterval()是指间歇调用,停止:clearInterval()

系统会话

常用系统会话alert()confirm()prompt()print(打印)find(查找)

location对象

location对象很特别,它既是window对象的属性,也是document对象的属性,换句话说window.locationdocument.location引用的是同一个对象。

使用location对象可以通过很多方式来改变浏览器的位置,首先是最常用的方法,就是使用assign()方法并为其传递一个URL,如下所示
loaction.assign("http://www.xiangzongliang.com");
如果是将location.hrefwindow.location设置为一个URL值,也会调用assign方法。
也可以通过hashsearchhostnamepathnameport属性设置为新值来改变URL。
每次修改location的属性(hash除外),页面都会以新URL重新加载。

最后一个方法是reload(),作用是重新加载当前显示的页面,页面会以最有效的方式重新加载页面,通常情况下,如果也面自上次请求以来并没有改变过,页面就会从浏览器缓存中重新加载,如果要强制从服务器重新加载,就需要设置下面一样:

  1. loaction.reload(); //重新加载(有可能从缓存中加载)
  2. location.reload(true); //重新加载(从服务器重新加载)

navigator对象

screen对象

screen对象基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器信息,

history对象

history对象保存着用户上网的历史记录,从窗口打开的那一刻算起,因为historywindow对象的属性,因此每个浏览器窗口、每个标签页乃至每个框架都有自己的history对象与特定的window对象关联。

  • go()方法接收一个参数,可以向前或者向后跳转任意页面。
  • history.back();向后退一页
  • history.forward()向前进一页
  • history.length表示历史记录的条数。

虽然history并不常用,但是在创建自定义的后退和前进按钮,以及检测当前页面是不是用户历史记录中的第一个页面时,还是必须使用它。

BOM小结

  • 在使用框架时,每个框架都有自己的window对象以及所有原生构造函数及其它函数副本,每个框架都保存在frames集合中,可以通过位置或通过名称来访问。
  • 有一些窗口指针,可以用来引用其它框架,包括父及框架。
  • top对象始终指向最外围的框架,也就是整个浏览器窗口。
  • parent对象表示包含当前框架的框架,而self对象则回指window
  • 使用location对象可以通过编程方式来访问浏览器的导航系统,设置相应属性,可以逐段或整体性地修改浏览器的URL。
  • 调用replace()方法可以导航到一个新的URL,同时该URL会替换浏览器历史记录中当前显示的页面。
  • navigator对象提供了与浏览器有关的信息,到底提供哪些信息,很大程度上取决于浏览器,不过也有一些公有的属性,存在与所有的浏览器。

客户端检测(第九章)

能力检测

DOM

操作节点

  • appendChild()用于向childNodes列表的末尾添加一个节点。
  • insertBefore()是吧节点放在childNodes()列表中某个特定的位置上,该方法接收两个参数:要插入的节点作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点。
  • replaceChild()方法接受两个参数:要插入的节点和要替换的节点。要替换的节点酱油这个方法返回并从文档树中被移除。
  • removeChild()单独的移除节点,被移除的节点将成为方法的返回值,

removeChild()replaceChild()从技术上来说,移除 的节点依然为文档所有,只不过在文档中已经没有了自己的位置。

其它方法

  1. 有两个方法是所有类型的节点都有的,第一个就是cloneNode(),用于创建调用这个方法的节点的一个完全相同的副本,该方法接收一个布尔值参数,表示是否执行深复制,在参数为true的情况下执行深复制,也就是赋值节点及其整个子节点树。在参数为false的情况下,执行浅复制,即只复制加点本身,复制后返回的节点副本属于文档所有,
  2. 最后一个方法是normalize(),这个方法唯一的作用就是处理文档树中的文本节点。由于解析器的实现或DOM操作等原因,可能会出现文本节点不包含文本,或者连续出现两个文本节点的情况,如果找到了空文本则删除它,如果找到了相邻的文本节点,则将它合并为一个文本节点。(暂时不知道怎么用)

查找元素

  • document.getElementById()接收一个参数,返回文档中出现的第一个ID元素,(IE7除外)
  • document.getElementByTagName()接收一个参数,返回符合标签名的零个或多个NodeList,
  • document.getElementByTagName()接收一个参数,返回具有相同name属性的NodeList。
  • document.anchors包含文档中所有带name特性的a元素。
  • document.forms包含文档中所有的from元素。
  • document.images包含文档中所有的<img>元素。
  • document.links包含文档中所有带href<a>元素。

文档写入

  • write()writeln()方法接收一个字符串参数,即要写入到输出流中,write()会写入原样。
  • writeln()则会在字符串末尾添加一个换行符( )。还可以使用这两个方法动态的包含外部资源,比如说javascript

    需要注意的是如下引入方式会被外部解释:
    document.write("<script type="text/javascript" src=""a.js">"+"</script>")这样编写,后面的</script>会被解释为外部的<script>标签匹配,结果文本。所以需要修改为</script>

  • open()close()分别是用于打开和关闭网页的输出流。

Element类型

取得特性

  • getAttribute()取得某一个属性
  • setAttribute()设置某一个属性
  • removeAttribute()移除某一个属性

创建元素

使用document.createElement()方法可以创建新元素。这个方法只接受一个参数,即要创建元素的标签名。
要把新元素添加到文档数中,可以使用appendChild()insertBefore()replaceChild()来添加。

评论:

烽火博一笑1510296128

老哥,歌听着不错