最近在看《JavaScript高级程序设计》这本书,面对着700多页的厚书籍,内心有点压力,因此我决定梳理一下。。探究一下到底怎么读这本书。本书的内容好像只有到ES5。。。因此只能之后慢慢加了。。。javascript
这一系列文章主要围绕:html
在看书以前,先大致看一下目录,将全书划分一下,对每个有大致的了解。可分为:java
把握重点
由于语法是个死的东西,因此在我看来,前面5章的内容是基础中的基础,然后面的6-7章的内容则是传达的一种思想-面向对象。因此在学习的时候,先把握重点。web
好了如今进入正题,如今能够打开书的第一章了,而后看完下面的预备知识,再看书。数组
预备知识:
Netscape Navigator是一个浏览器,浏览器!!!如下简称NN浏览器。浏览器
总结梳理
关于版本的更新问题,有人作了一张图,拿来了,不知道有没有问题。服务器
关注的重点
这里面有一个重要的知识就是MIME类型,在后面会遇到,若是忘了的话,会看的很糊涂。
MIME类型:编写代码使用的脚本语言的内容类型 能够是text/html 也能够是text/javascript数据结构
总结梳理
如何在浏览器中使用JavaScript呢?须要用到HTML。因此就引出了几个问题app
按照这个内容本身想一下,在书中均可以找到答案。ide
和c java语言有不少类似之处,因此在这里就重点说一下不一样之处。
1. 松散类型
var message;
var message = 16;
message = "hello";
也就是一个变量可以存全部的类型。甚至咱们均可以不用加var
像这样定义就会直接建立全局变量message = 16
(由于有了window对象,因此实际是window.message = 16')。
2. 没有块级做用域
不像其余语言{}
内容里面的都是块级做用域,而在JavaScript中是没有这一说的。它的做用域法则是不同的。
在JavaScript中,把这个东西叫作,执行环境。注意,执行环境只分为两种全局执行环境(除函数以外的环境)和局部执行环境(只有函数内部的区域是局部的。)每一个执行环境都有一个与之相关联的变量对象(全部的变量与函数保存在里面)
对于全局执行环境来讲,对象就是window对象,而对于局部(函数)环境来讲,称为活动对象(最开始至包含arguments对象)
环境结束就会销毁,其里面的变量,函数。全局环境的关闭是页面关闭或者浏览器关闭,而局部环境的关闭是指函数结束。
由于这个道理就能够在函数内部创建相同的变量。(两个对象不一样)
其查询标识符是从下道上的一个过程,例以下面的代码:
var color = "blue"; function getColor() { var color = "red"; return color; } alert(getColor()); //"red"
搜索的过程就是先搜索getColor()的变量对象,是否包含color,是就结束,否就找下一个变量对象(此例子中是全局对象即window对象),都找不到的话就返回undefined
3.[]表示法
和其余语言不一样,在javaScript中[]不止用在数组中,它还能够用在对象上面。如咱们如今创建一个名为dog的对象,若是咱们想要访问name属性,那么能够这么写:dog["name"],【注意】属性是以字符串的形式的。
看完了不一样之处,最难理解的东西就已经掌握了,其余的就是一些细小的东西了,只须要按照必定的逻辑背一下熟悉熟悉,多练多实践,我就以为够了,这也是笔者的见解。
学习的脉络就是根据不一样的类型开始逐一熟悉。
1.数据类型
注意数据类型指的是数据的类型。
分为五种基本类型,和一种复杂类型。
五种基本类型:Undefined,Null,Boolean,Number,String
一种复杂类型:Object.
提到这个就很天然的想到,既然是松散类型的,该怎么检测给定变量的数据类型呢?
答案是typeof操做符,注意是操做符。
他返回的是:"undefined" "string""number" "boolean" "object" "function"
用法:typeof 变量
或typeof(变量)
2.Undefined类型
Undefined类型我把它理解为未被定义过的类型,是一个undefined值,
这有两种状况:
体会一下两个的区别:
alert(message);//会显示错误信息 alert(typeof message);//"undefined"值
3.Null
Null类型只有一个null值的类型。null值是一个空对象指针,因此typeof null
返回的是"object"
而undefined就是由null值派生出来的。
因此undefined == null
返回的是true
4.Number类型
转换问题:
这是一个很清晰的脉络,对于不一样类型的值怎么转换是一个很大的问题。
因此方法有Number()、parseInt()、parseFloat().
不一样方法的规则是什么?
整数类型:
十进制的表示,八进制的表示,以及16进制的表示。
浮点数类型:
自动转换整数的特色,e表示法。
数值范围:
最大和最小的范围是?超出范围的数字如何表示?
NaN:
NaN是一个特殊的值。有两个特色
5.String类型:
Unicode字符组成的字符串。
转换问题
一样是转换问题,这一个脉络仍是很清晰。
String(),toString()方法。它们分别转换的规则是什么?对于数值型的转换有没有什么不同的地方?对于null和undifined呢?
6.引用类型
为何会多出一个引用类型呢?所谓引用类型实际是一个数据结构,是描述一类对象的属性和方法。和“类”类似。它与对象是什么关系呢?对象是某一个引用类型的实例。
在上面说的一种复杂数据类型Object就是指的是引用类型,是一种大的概念。
如何学习这里面的内容呢?因为对象就是一系列的属性和方法,因此重点是经常使用的属性和方法,而这一点也没有什么难度,无非就是熟练的过程。仍是多练。
引用类型的建立
new标识符。如 var message = new Object();
var item = new Array();
如下列出几种重要的引用类型,对于方法和属性的细节,暂时抛弃。
1) Object类型
对于Object的建立除了new 还有 字面量,即:
var message = { name : helo, color : red, ... }
【注意】在使用字面量的时候,是不调用构造方法的。
2)Array类型
一样的建立一个Array的对象也有不一样的方法:
例如:var colors = new Array(2);//数组的长度为2.
var colors = ["red","blue","green"];//用[]来建立一个特定的数组
固然JavaScript中的数组更加神童广大,最大的区别就是:数组长度可变。
相关的方法,请具体查阅书籍。
3)Date类型
4)RegExp类型
5)Function类型
这里要提一下了,在Javascript中,每一个函数都是Function类型的实例,也能够说是对象。
因此能够这么写代码:var sum = new Function("num1","num2","return num1 + num2");
可是不建议。
另外两种定义一个函数的方法是:function sum (num1,num2) {...}//函数声明
var sum = function(num1,num2){...}//函数初始化
这两种定义的方式是有区别的,
【函数声明】:在代码执行以前,解析器读取并将函数声明添加到执行环境中去。因此如下代码是没有问题的。
alert(sum(10,10)); function sum(num1,num2){ return num1 + num2; }
【函数自定义】:则是在执行到函数以前,是不会保存的。因此如下代码会出现“unexpected identifier”错误
alert(sum(10,10)); var sum = function(num1,mum2) { return num1 + num2; };
另外一个方面既然函数是对象的话,函数名是指针变量,那么就能够把这个函数变量,看成参数,传递给另外一个函数。
同时它还应该有属性和方法。具体有哪些属性本身回忆或查阅。
在这里重点提一下 prototype属性,对于引用类型而言,prototype是保存他们全部实例方法的真正所在。(后面会更加详细的讲解。)
6)基本包装类型
为了便于操做基本类型,又建立出了特殊的引用类型,Boolean、Number、String。
实际上读取一个基本类型,他就会自动的建立各自的实例,执行相关操做,而后就会销毁
如:
var s1 = "some text"; var s2 = s1.substring(2);
下面的代码就体现了销毁过程
var s1 = "some text";//在内部的过程 s1.color = "red"; alert(s1.color);
在第一行代码中,建立了一个实例,建立了字符串,随之销毁,第二行又从新建立了一个实例,附上red后,销毁,在第三行中在执行中,又建立了一个实例,此时实例的属性是undefined。
同时Object构造函数也具备这个功能。
如:
var obj = new Object("some text");//自动返回基本包装类型的实例 alert(obj instanceof String);//true
三种各自的包装类型详细方法本身回忆。
7)单体内置对象
这些书有一大特色,就是里面的名词真的让你心惊胆战,明明很简单的事情,非要弄个你不熟悉的名字吓唬你。
单体内置对象,就是不依赖宿主环境的对象,在程序执行以前就已经存在。有两个 Global和Math
Global对象
书中写的颇有意思,叫作“终极兜底儿对象”,全部不属于其余对象的属性和方法,最终都是他的属性和方法
你必定想知道以前不是有window对象吗?他们两个是一个什么关系,如今先保留这个问题。
Global是一个虚拟的东西,他不能new出来,可是倒是真实存在的。全部在全局做用域中定义的属性和函数,最终都是它的属性和方法。其里面还有一些内置的函数,诸如咱们以前了解过的isNaN(),isFinite(),parseInt(),parseFloat()等等,都是Global的方法。
如今咱们就来讲一下window是一个什么东西,以前说过在全局做用域中定义的属性和方法,其实均可以用window.XX来访问获得,由于不能直接访问Global对象,因此window对象实现了Global对象的一部分,全局做用域中属性和函数,就都成为了window对象的属性和方法。
接下来Global对象的属性和方法请自行回忆脑补。
Math对象
对于Math对象没有什么难理解的,一样沿着他的属性和方法回忆就好。。
首先这一思想是最重要的,也是之后的基础,因此脉络清楚对于有好处。
到目前为止,咱们怎么两种方法建立对象:
function createPerson(name,age,job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var person1 = createPerson("Nicholas",29,"Software Engineer"); var person2 = createPerson("Greg",27,"Doctor");
function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); }; } var person1 = new Person("Nicholas",29,"Software Engineer"); var person2 = new Person("Greg",27,"Doctor");
用构造方法来建立的实例中,这两个对象都有一个constructor(构造函数)属性,该属性指向Person。
可是目前的这个构造方法建立对象是有问题的,回想一下每一个函数其实都是Function的一个实例,在以上建立person1和person2的时候,虽然两个函数是同样的,可是须要在里面建立两个不一样的Function实例,因此能够改进一下:
function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); } var person1 = new Person("Nicholas",29,"Software Engineer"); var person2 = new Person("Greg",27,"Doctor");
这样一来虽然能够解决问题,可是若是有不少函数的话,就须要在外面定义好多函数,就体现不了封装的思想了。为了解决这一问题,就出现了原型。(prototype)
关于原型
每一个对象都有一个私有属性(称之为 [[Prototype]]),它持有一个链接到另外一个称为其 prototype 对象(原型对象)的连接。该 prototype 对象又具备一个本身的原型,层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并做为这个原型链中的最后一个环节
再看一下书中的那个示意图,会很明白。
关于几个方法:isPrototypeOf()
是否为某个对象的原型Person.prototype.isPrototypeOf(person1)//true
Object.getPrototypeOf()
获得某个对象的原型。alert(Object.getPrototypeOf(person1).name;//"Nicholas"
hasOwnProperty()
方法能够检测一个属性是否存在实例中。alert(person1.hasOwnProperty("name"));//true
function Person() {} Person.prototype = { constructor:Person; name:"nigulasi", age:29, job:"Software Engineer", sayName:function() { alert(this.name); } };
以上两种方式都有各自的缺点,取他们的长处组合,是一个很好的方法。
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.friends=["Shelby","Court"]; } Person.prototype = { constructor:Person; sayName:function(){ alert(this.name); } };
实例属性都是在构造函数中定义的,而全部实例共享的属性constructor和方法sayName()则是在原型中定义的。
原型链继承
//组合方法建立父级对象 function Animal(name,age) { this.name=name; this.age = age; } Dog.prototype.getName() { alert(this.name); } //组合方法建立对象,利用原型继承 function Dog(name,age) { this.name = name; this.age = age; } //实现继承 Dog.prototype = new Animal();
构造函数实现继承
function Super() { this.colors = ["red","blue","green"]; } function Sub() { //继承自Super Super.call(this);//使用apply()和call()方法能够在新建立的对象上执行构造函数。 }
组合继承
一样集两种之所长。
function Super(name) { this.name = name; this.colors = ["red","blue","green"]; } Super.prototype.sayName = function(){ alert(this.name); }; function Sub(name,age) { //继承属性 Super.call(this.name); this.age = age; } //继承方法 Sub.prototype = new Super(); sub.prototype.contructor =sub Sub.prototype.sayAge = function() { alert(this.age); };