Javascript精细笔记

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


 

 

 以上就是函数的执行顺序,也解释了为什么函数内部可以访问到外部的变量,而外部不可以访问到内部的变量

导致报错,也就好比 儿子可以问父亲要钱 可以问爷爷要钱,但是反过来是不是不行啊。

 

 

 

 

 

 

 

                

      

  

 

posted @ 2018-09-20 22:04  1998丶1019  阅读(317)  评论(0编辑  收藏  举报