javascript原理解析.docx

上传人:b****5 文档编号:4043707 上传时间:2022-11-27 格式:DOCX 页数:20 大小:289.80KB
下载 相关 举报
javascript原理解析.docx_第1页
第1页 / 共20页
javascript原理解析.docx_第2页
第2页 / 共20页
javascript原理解析.docx_第3页
第3页 / 共20页
javascript原理解析.docx_第4页
第4页 / 共20页
javascript原理解析.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

javascript原理解析.docx

《javascript原理解析.docx》由会员分享,可在线阅读,更多相关《javascript原理解析.docx(20页珍藏版)》请在冰豆网上搜索。

javascript原理解析.docx

javascript原理解析

1.Javasript引擎

1.1什么是JavaScript解析引擎?

简单地说,JavaScript解析引擎就是能够“读懂”JavaScript代码,并准确地给出代码运行结果的一段程序。

比方说,当你写了 vara=1+1; 这样一段代码,JavaScript引擎做的事情就是看懂(解析)你这段代码,并且将a的值变为2。

学过编译原理的人都知道,对于静态语言来说(如Java、C++、C),处理上述这些事情的叫编译器(Compiler),相应地对于JavaScript这样的动态语言则叫解释器(Interpreter)。

这两者的区别用一句话来概括就是:

编译器是将源代码编译为另外一种代码(比如机器码,或者字节码),而解释器是直接解析并将代码运行结果输出。

比方说,firebug的console就是一个JavaScript的解释器。

但是,现在很难去界定说,JavaScript引擎它到底算是个解释器还是个编译器,因为,比如像V8(Chrome的JS引擎),它其实为了提高JS的运行性能,在运行之前会先将JS编译为本地的机器码(nativemachinecode),然后再去执行机器码(这样速度就快很多),相信大家对JIT(JustInTimeCompilation)一定不陌生吧。

我个人认为,不需要过分去强调JavaScript解析引擎到底是什么,了解它究竟做了什么事情我个人认为就可以了。

对于编译器或者解释器究竟是如何看懂代码的,翻出大学编译课的教材就可以了。

这里还要强调的就是,JavaScript引擎本身也是程序,代码编写而成。

比如V8就是用C/C++写的。

1.2JavaScript解析引擎与ECMAScript是什么关系?

JavaScript引擎是一段程序,我们写的JavaScript代码也是程序,如何让程序去读懂程序呢?

这就需要定义规则。

比如,之前提到的vara=1+1;,它表示:

∙左边var代表了这是申明(declaration),它申明了a这个变量

∙右边的+表示要将1和1做加法

∙中间的等号表示了这是个赋值语句

∙最后的分号表示这句语句结束了

上述这些就是规则,有了它就等于有了衡量的标准,JavaScript引擎就可以根据这个标准去解析JavaScript代码了。

那么这里的ECMAScript就是定义了这些规则。

其中ECMAScript262这份文档,就是对JavaScript这门语言定义了一整套完整的标准。

其中包括:

∙var,if,else,break,continue等是JavaScript的关键词

∙abstract,int,long等是JavaScript保留词

∙怎么样算是数字、怎么样算是字符串等等

∙定义了操作符(+,-,>,<等)

∙定义了JavaScript的语法

∙定义了对表达式,语句等标准的处理算法,比如遇到==该如何处理

∙⋯⋯

标准的JavaScript引擎就会根据这套文档去实现,注意这里强调了标准,因为也有不按照标准来实现的,比如IE的JS引擎。

这也是为什么JavaScript会有兼容性的问题。

至于为什么IE的JS引擎不按照标准来实现,就要说到浏览器大战了,这里就不赘述了,自行Google之。

所以,简单的说,ECMAScript定义了语言的标准,JavaScript引擎根据它来实现,这就是两者的关系。

1.3JavaScript解析引擎与浏览器又是什么关系?

简单地说,JavaScript引擎是浏览器的组成部分之一。

因为浏览器还要做很多别的事情,比如解析页面、渲染页面、Cookie管理、历史记录等等。

那么,既然是组成部分,因此一般情况下JavaScript引擎都是浏览器开发商自行开发的。

比如:

IE9的Chakra、Firefox的TraceMonkey、Chrome的V8等等。

从而也看出,不同浏览器都采用了不同的JavaScript引擎。

因此,我们只能说要深入了解哪个JavaScript引擎。

2.Javascript中的__proto__,prototype和constructor

2.1__proto__

javascript中一切都是对象,每个对象都是基于原型对象创建的,每个对象中都有__proto__属性,这个属性指向的就是它基于的原型对象。

__proto__属性是系统(浏览器)自动给创建的,在对象被创建的时候自动指向基于的原型对象。

比如:

functionFoo(){

}

varfoo=newFoo();

foo.__proto__指向的就是Foo.prototype

因为Foo函数本身也是个对象,所以Foo.__proto__指向的是Function.prototype

Function.prototype本身也是对象,所以Function.prototype.__proto__指向的是Object.prototype

2.2prototype

只有构造函数对象才有prototype属性,构造函数的作用是创建对象,创建对象的时候,它要知道这个对象基于哪个原型来创建,这个prototype指向的就是这个原型。

prototype属性也是系统(浏览器)给创建的,并指向创建对象时基于的原型。

注意不是构造函数本身基于的原型,本身基于的原型都是Function.prototype。

比如:

functionFoo(){

}

//系统自动把Foo的prototype属性指向Foo.prototype

//所以,newFoo()的时候,就基于Foo.prototype来创建,

//foo.__proto__就是Foo.prototype

varfoo=newFoo();

foo.__proto__和Foo.prototype指向的都是Foo.prototype。

自定义一个Foo构造函数的时候,系统默认会自动指定一个Foo.prototype原型对象,其实就是一个Object对象。

2.3constructor

只有原型对象才有constructor属性,而且也是系统(浏览器)给创建的。

前面说过构造函数对象的prototype属性会指向一个原型对象,那么这个原型对象中的constructor属性指向的就是这个构造函数。

constructor属性其实是给自定义对象使用的,自定义对象通过constructor属性就可以知道自己是用哪个构造函数new出来的。

比如:

functionFoo(){

}

varfoo=newFoo();

alert(foo.constructor)//functionFoo(){}

//foo中没有constructor,foo访问的是它的原型Foo.prototype中的constructor属性。

一个对象被new出来以后,就可以知道自己的两方面事情:

1.通过foo.__proto__,可以知道自己是基于哪个原型创建出来的,相当于自己的父类

2.通过foo.constructor,可以知道自己是用哪个构造函数构造出来的相当于自己的类

2.4构造器/函数的__proto__都指向Function.prototype,它是一个空函数(Emptyfunction)

Number.__proto__===Function.prototype//true

Boolean.__proto__===Function.prototype//true

String.__proto__===Function.prototype//true

Object.__proto__===Function.prototype//true

Function.__proto__===Function.prototype//true

Array.__proto__===Function.prototype//true

RegExp.__proto__===Function.prototype//true

Error.__proto__===Function.prototype//true

Date.__proto__===Function.prototype//true

JavaScript中有内置(build-in)构造器/对象共计12个(ES5中新加了JSON),这里列举了可访问的8个构造器。

剩下如Global不能直接访问,Arguments仅在函数调用时由JS引擎创建,Math,JSON是以对象形式存在的,无需new。

它们的__proto__是Object.prototype。

如下

Math.__proto__===Object.prototype//true

JSON.__proto__===Object.prototype//true

上面说的“所有构造器/函数”当然包括自定义的。

如下

//函数声明

functionPerson(){}

//函数表达式

varMan=function(){}

console.log(Person.__proto__===Function.prototype)//true

console.log(Man.__proto__===Function.prototype)//true

这说明什么呢?

所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身。

所有构造器都继承了Function.prototype的属性及方法。

如length、call、apply、bind(ES5)。

Function.prototype也是唯一一个typeofXXX.prototype为“function”的prototype。

其它的构造器的prototype都是一个对象。

如下

console.log(typeofFunction.prototype)//function

console.log(typeofObject.prototype)//object

console.log(typeofNumber.prototype)//object

console.log(typeofBoolean.prototype)//object

console.log(typeofString.prototype)//object

console.log(typeofArray.prototype)//object

console.log(typeofRegExp.prototype)//object

console.log(typeofError.prototype)//object

console.log(typeofDate.prototype)//object

console.log(typeofObject.prototype)//object

噢,上面还提到它是一个空的函数,alert(Function.prototype)下看看。

知道了所有构造器(含内置及自定义)的__proto__都是Function.prototype,那Function.prototype的__proto__是谁呢?

相信都听说过JavaScript中函数也是一等公民,那从哪能体现呢?

如下

Function.prototype.__proto__===Object.prototype//true

这说明所有的构造器也都是一个普通JS对象,可以给构造器添加/删除属性等。

同时它也继承了Object.prototype上的所有方法:

toString、valueOf、hasOwnProperty等。

最后Object.prototype的__proto__是谁?

Object.prototype.__proto__===null//true

已经到顶了,为null。

2.5对象的__proto__都指向其构造器的prototype

上面测试了所有内置构造器及自定义构造器的__proto__,下面再看看所有这些构造器的实例对象的__proto__指向谁?

先看看JavaScript引擎内置构造器

varobj={name:

'jack'}

vararr=[1,2,3]

varreg=/hello/g

vardate=newDate

varerr=newError('exception')

console.log(obj.__proto__===Object.prototype)//true

console.log(arr.__proto__===Array.prototype)//true

console.log(reg.__proto__===RegExp.prototype)//true

console.log(date.__proto__===Date.prototype)//true

console.log(err.__proto__===Error.prototype)//true

再看看自定义的构造器,这里定义了一个Person

functionPerson(name){

this.name=name

}

varp=newPerson('jack')

console.log(p.__proto__===Person.prototype)//true

p是Person的实例对象,p的内部原型总是指向其构造器Person的prototype。

每个对象都有一个constructor属性,可以获取它的构造器,因此以下打印结果也是恒等的

functionPerson(name){

this.name=name

}

varp=newPerson('jack')

console.log(p.__proto__===p.constructor.prototype)//true

上面的Person没有给其原型添加属性或方法,这里给其原型添加一个getName方法

functionPerson(name){

this.name=name

}

//修改原型

Person.prototype.getName=function(){}

varp=newPerson('jack')

console.log(p.__proto__===Person.prototype)//true

console.log(p.__proto__===p.constructor.prototype)//true

可以看到p.__proto__与Person.prototype,p.constructor.prototype都是恒等的,即都指向同一个对象。

如果换一种方式设置原型,结果就有些不同了

functionPerson(name){

this.name=name

}

//重写原型

Person.prototype={

getName:

function(){}

}

varp=newPerson('jack')

console.log(p.__proto__===Person.prototype)//true

console.log(p.__proto__===p.constructor.prototype)//false

这里直接重写了Person.prototype(注意:

上一个示例是修改原型)。

输出结果可以看出p.__proto__仍然指向的是Person.prototype,而不是p.constructor.prototype。

这也很好理解,给Person.prototype赋值的是一个对象直接量{getName:

function(){}},使用对象直接量方式定义的对象其构造器(constructor)指向的是根构造器Object,Object.prototype是一个空对象{},{}自然与{getName:

function(){}}不等。

如下

varp={}

console.log(Object.prototype)//为一个空的对象{}

console.log(p.constructor===Object)//对象直接量方式定义的对象其constructor为Object

console.log(p.constructor.prototype===Object.prototype)//为true,不解释

上面代码中用到的__proto__目前在IE6/7/8/9中都不支持。

IE9中可以使用Object.getPrototypeOf(ES5)获取对象的内部原型。

varp={}

var__proto__=Object.getPrototypeOf(p)

console.log(__proto__===Object.prototype)//true

 

3.JavaScript创建对象

通过JavaScript,您能够定义并创建自己的对象。

创建新对象有两种不同的方法:

1.定义并创建对象的实例

2.使用函数来定义对象,然后创建新的对象实例

3.1创建直接的实例

3.1.1对象直接量

varempty={};//Anobjectwithnoproperties

varpoint={x:

0,y:

0};

varcircle={x:

point.x,y:

point.y+1,radius:

2};

varhomer={

"name":

"HomerSimpson",

"age":

34,

"married":

true,

"occupation":

"plantoperator",

'email':

homer@

};

3.1.2通过new创建对象

vara=newArray();//Createanemptyarray

vard=newDate();//Createanobjectrepresentingthecurrentdateandtime

varr=newRegExp("javascript","i");//Createapattern-matchingobject

这个例子创建了对象的一个新实例,并向其添加了四个属性:

Person=newObject();

Person.firstname="Bill";

Person.lastname="Gates";

Person.age=56;

Person.eyecolor="blue";

3.2使用对象构造器

本例使用函数来构造对象:

functionPerson(firstname,lastname,age,eyecolor)

{

this.firstname=firstname;

this.lastname=lastname;

this.age=age;

this.eyecolor=eyecolor;

}

3.2.1创建JavaScript对象实例

一旦您有了对象构造器,就可以创建新的对象实例,就像这样:

varmyFather=newPerson("Bill","Gates",56,"blue");

varmyMother=newPerson("Steve","Jobs",48,"green");

3.2.2把属性添加到JavaScript对象

您可以通过为对象赋值,向已有对象添加新属性:

假设PersonObj已存在-您可以为其添加这些新属性:

firstname、lastname、age以及eyecolor:

Person.firstname="Bill";

Person.lastname="Gates";

Person.age=56;

Person.eyecolor="blue";

x=Person.firstname;

在以上代码执行后,x的值将是:

Bill

3.2.3把方法添加到JavaScript对象

方法只不过是附加在对象上的函数。

在构造器函数内部定义对象的方法:

functionPerson(firstname,lastname,age,eyecolor)

{

this.firstname=firstname;

this.lastname=lastname;

this.age=age;

this.eyecolor=eyecolor;

this.changeName=changeName;

functionchangeName(name)

{

this.lastname=name;

}

}

changeName()函数name的值赋给Person的lastname属性。

现在您可以试一下:

myMother.changeName("Ballmer");

3.3使用Object.create()

Object.create(prototype,descriptors):

创建一个具有指定原型且可选择性地包含指定属性的对象。

该函数是一个静态函数。

参数:

prototype必需。

要用作原型的对象。

可以为null。

descriptors可选。

包含一个或多个属性描述符的JavaScript对象。

“数据属性”是可获取且可设置值的属性。

数据属性描述符包含value特性,以及writable、enumerable和configurable特性。

如果未指定最后三个特性,则它们默认为false。

只要检索或设置该值,“访问器属性”就会调用用户提供的函数。

访问器属性描述符包含set特性和/或get特性。

varo1=Object.create(null);//o1不继承任何属性和方法

varo2=Object.create({x:

1,y:

2});//o2继承了属性x和y

varo3=Object.create(Object.prototype);//o3和newObject()一样

3.4JavaScript类

JavaScript是面向对象的语言,但JavaScript不使用类。

在JavaScript中,不会创建类,也不会通过类来创建对象(就像在其他面向对象的语言中那样)。

JavaScript基于prototype,而不是基于类的。

4.JavaScript事件监听

4.1事件监听的三种方式

4.1.1直接在代码上加载事件

展开阅读全文
相关搜索

当前位置:首页 > 幼儿教育 > 唐诗宋词

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1

text1text2