Mosaic,是互联网历史上第一个获普遍使用和能够显示图片的网页浏览器。于1993年问世。
作者:Brendan Eich
浏览器的组成:
1.shell部分(也就是我们顾名思义的外壳)
2.内核部分
2.1.渲染引擎(语法规定和渲染)
2.2.js引擎
2.3.其他模块
扩展部分:
2008年Google发布最新浏览器Chrome,它是采用优化后的javascript引擎,引擎代号V8,因能把js代码直接转化为机械码来执行,进而以速度快而闻名。
ChromeV8引擎是由c语言编写的 v8引擎直接可以将内容转换成0,1的数字,所以Chrome比任何浏览器都要快,如果没有v8引擎需要将汇编语言转成成C语言在转换成javascript语言。
编译语言(C,C++)
特点:先全部解释,在全部执行。
优点:快
缺点:移植性不好(不能跨平台)
解释性语言(Javascript,php,python)
特点:解释一行,执行一行
优点:跨平台
缺点:稍微慢一点
另外注意的一点就是java与其他的语言是不同的,它历史叫做oak语言
解释方式:.java文件 -> 通过javac命令 -> 编译 -> .class文件 -> jvm虚拟机解释执行
javascript语言的特点:
1、解释性语言(不需要编译成文件,跨平台)
2、单线程
开始学习javascript
js三大部分:ECMAScript,DOM,BOM
js基本语法:
变量(variable)
变量声明 var a = 1;
变量赋值 a = 1;
命名规则
1、变量名必须以英文字母,_,$开头
2、变量名可以包括英文字母、_、$、数字
3、不可以用系统的关键字、保留字作为变量名
js中的保留字和关键字
基本语法
一、js中的原始值和引用值
1.原始值(stack栈,不可改变的)先进后出
Number(数字),String(字符串),Boolean(布尔值),undefined(undefined),null(空,占位符)
特点:拷贝的数,不影响其他的值
例如:var a = 10;
b = a;
b = 20;
console.log(b) // 20
2.引用值(heap堆)
Array(数组),Object(对象),function(函数),Date(日期),RegExp(正则表达式)
特点:拷贝的是地址,影响其他的值
例如:var arr = [1,2];
arr1 = arr;
arr1.push(3);
console.log(arr) // 1,2,3
如下图一cst和zx指向的是同一个地址,所以只要改变就会发生变化。
如下图二 a 赋值给b 是拷贝了一个副本,之后b在发生变化,和a没有任何关系
图一
图二
js语句基本规则
语句后面要用分号结束“;”
js语法错误会引发后续代码终止,但不会影响其它js代码块
书写格式要规范,“= + / -”两边都应该有空格
运算操作符
“+”
1.数学运算、字符串链接
2.任何数据类型加字符串都等于字符串
“-”,“*”,“/“,“%”,”=“,“()”
优先级”=“最弱,”()”优先级较高
“++”,“- -”,”+=“,“-=”,“/=“,“*=”,“%=”
被认定为假的六个值:
undefinnde,null,false,null,0," "
逻辑运算符:
&&:先看第一个表达式转换成布尔值的结果,如果结果为真,那么它会看第二个表达式的结果转换成布尔值的结果(undefined,null,false,null,0,
" "这些值都是false),然后如果只有两个表达式的话,只看到第二个表达式就可以返回该表达式的结果了。如果第一个为false,就可以直接返回false了。
||:只有有一个表达式为真就返回真。
! :取反字符
for循环的底层原理:
for(var i = 0; i < 10; i++){}的实现
第一步:var i= 0;
第二步:if(i < 10){
console.log('a')
}
第三步:i++;
第四步:if(i < 10){
console.log('a')
}
......
注意如果for循环只写中间的一个条件,那么就是while循环
for(;i < 10;){} === while(i < 10){}
switch,case语句相当于if{}else{}
如:
if(a == 10){
console.log(10)
}else if(a == 20){
console.log(20)
}
换成switch,case
switch(a){
case 10 :
return 10;
case 20:
return 20;
}
还有一点需要注意的一旦用了return 后面的代码就不会执行了,就不用break了
二:typeof
首先需要知道typeof能够,且只能够返回的六种类型
number,string,boolean,object,function,undefined,这些结构之前已经解释过了,就不一一解释了。
类型转换:
显示类型转换:
Number:强行转换成数字类型,注意的是undefined不能转换成数字
parseInt:转换成整型,其他的NaN,会转换成Number类型,从数字最后一位开始截取下来。如 typeof('123abc') // number 123;
另外一点:parseInt(num,radio) -> radio为基地转换成10进制的数
parseFloat:转换成浮点型,并保留一位小数;
string:转换成字符串,写什么都是字符串;
boolean:转换成布尔值,除了" ",其他都是为true;
toString:也是转换成字符串,和string的区别在于用法不同,(undefined,null)不可用toString这个方法;
另外一点:toString()括号内可以跟目标进制的数
隐式类型转换:
isNaN -> Number()
++/ -- +/-(一元正负运算符) -> Number()
+ 加号 -> String()
*/% -> Number()
&& | ! -> Number()
注意 !== 和 === 不发生类型转换
三、函数
1.初始函数:
定义方式:
函数声明:function (){}
函数表达式:
命名函数表达式:var test = function test() {}
匿名函数表达式(也称为函数表达式):var test = function () {}
实参和形参
例如:function test(a,b) {console.log(a,b)} test(1,2) //a,b称为形式参数,简称为形参; 1,2称为实际参数,简称为实参;
注意:函数function test(a,b){相当于隐式的var a,b;}
查看形参的长度:test.length(函数名的长度)
查看形参的长度:arguments.length(实参列表)
重点:函数里面的实参和形参存在映射的关系,只要其中它们有一个发生了变化另外一个也会发生变化,即使它们都是原始值,这是函数的特性
如果形参的长度大于实参的长度多出来的位数不会发生映射的关系。
另外的一个知识点,return:
(1)如果没有写return,则在函数的最后系统会自动帮你加上return,就好比没有写分号一样
(2)如果写了return,下面的代码则不会继续执行了.return返回的必须定义了容器来接收它,不然不会显示。
2.预编译:
大部分人都会记住两句话叫做:
(1).函数声明整体提升 意思是:函数声明不管在哪里调用都是好使的.
例如: test() //1 function test(){console.log(1)} 就算在前面执行依然能够打印出1
(2)变量 声明提升 注意了这句话需要分开来读 变量 声明提升 而不是 变量声明提升 什么意思呢? 是这样的:
例如 var a = 10;这叫做变量声明 如果你在之前打印 a 会出现undefined 为什么会这样呢 因为系统内部只会把 var 提前到最顶端 而赋值语句
不会提升到最顶部 这也是JavaScript语言的特点,所以会出先undefined。
注意点: 不管在全局还是在局部声明变量,必须要通过 var,let(这是es6会学到的)来声明不然归window所有。
例如:function test() {var a = b = 10} test() console.log(window.b,window.a) //10,undefined 因为b是没有进行变量声明得到的值所以归
window所有 而a就是通过变量声明来的值,所以window上面是访问不到的.这个b也可能叫做"暗示全局变量"
预编译是发生在函数执行的前一刻(四部曲):
(1):创建AO对象(Activation Object)又称为执行期上下文。
(2):找形参和变量声明,将变量和形参名作为Ao的属性名,值为undefined.
(3):将实参和形参相统一.
(4):在函数体里面找函数声明.值赋予函数体
写一个小例子就懂了:
function fn(a){
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a)
var b = function () {}
console.log(b)
function d(){}
}
fn(1)
这个例子如果你只知道之前两句话是解不出来的,那我们就一步一步的分析一下吧。
第一步创建Ao对象:
AO{}
第二步找形参和变量声明,值为undefined
AO{a:undefined,b:undefined}
第三步将实参和形参相统一
AO{a:1 b:undefined}
第四步找函数声明 注意是 functio test() {} 而不是 var test = function () {}
AO{a:function a(){},b:undefined,d:function d() {}}
所以值为// function a() {},123,123,function (){}
3.作用域:
[[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,
[[scope]]就是其中一个。[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,
函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,执行上下文被销毁。
查找变量顺序:从作用域链的顶端依次向下查找。
看图解释:
a函数在定义的时候产生一个Go(global object)放到作用域的最顶端。
a函数在执行的前一刻,也就是我们所说的预编译过程,创建一个执行期上下文对象放到作用域的最顶端。
b函数在创建的时候,直接可以拿到a函数的劳动成果放到自己作用域的最顶端。
b函数执行生成一个执行期上下文,放到自己作用域最顶端,然后将a的劳动成果依次向下,需要注意的点
看图中的标注
上面的图解是作用域的大致流程。
在写一个小的实例:
function a() {
function b() {
function c() {
}
c() }
b()
}
a()
执行过程:
a 定义 a.[[scope]] -> 0 : Go
a 执行 a.[[scope]] -> 0 : aAo
1 :Go
b 定义 b.[[scope]] -> 0 : aAo
1 : Go
b 执行 b.[[scope]] -> 0 : bAo
1 : aAo
2 : Go
c 定义 c.[[scope]] 0 : bAo
1 : aAo
2 : bAo
c 执行 c.[[scope]] 0 : cAo
1 : bAo
2 : aAo
3 : Go
以上就是函数的执行顺序,也解释了为什么函数内部可以访问到外部的变量,而外部不可以访问到内部的变量
导致报错,也就好比 儿子可以问父亲要钱 可以问爷爷要钱,但是反过来是不是不行啊。