1.初识JavaScript
1.1.什么是JavaScript
JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web 页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,例如 Node.js、 Apache CouchDB 和 Adobe Acrobat。JavaScript 是一种基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
1.2.JavaScript的组成部分
- ECMAScript,描述了该语言的语法和基本对象。
- 文档对象模型(DOM),描述处理网页内容的方法和接口。
- 浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口。
1.3.JavaScript的历史
1994 年,网景公司(Netscape)发布了 Navigator 浏览器0.9版。这是历史上第一个比较成熟的网络浏览器,轰动一时。但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。网景公司急需一种网页脚本语言,使得浏览器可以与网页互动。
1995年5月,网景公司做出决策,未来的网页脚本语言必须"看上去与 Java 足够相似",但是比 Java 简单,使得非专业的网页作者也能很快上手。这个决策实际上将 Perl、Python、Tcl、Scheme 等非面向对象编程的语言都排除在外了。
JavaScript最初由Netscape的Brendan Eich设计,创始人Brendan Eich只用了10天就把JavaScript设计出来了;最初将其脚本语言命名为LiveScript,后来Netscape在与Sun合作之后将其改名为JavaScript。JavaScript最初受Java启发而开始设计的,目的之一就是“看上去像Java”,因此语法上有类似之处,一些名称和命名规范也借自Java,但JavaScript的主要设计原则源自Self和Scheme。
JavaScript诞生于1995年,当时的主要目的是处理由以前服务器语言负责的一些没有填写的必填域,是否输入了无效的值。在web日益流行的同时,人们对客户端脚本语言的需求也越来越强烈,那时绝大多数因特网用户使用的速度仅为28.8kbit/s的猫上网,但网页的大小和复杂性却不断增加,未完成简单的表单验证而与服务器交换数据只会加重用户和服务器的负担。
JavaScript发展历史
(1)JavaScript被设计出来后最初命名为Mocha,1995年9月在Netscape Navigator 2.0的Beta版中改名 为LiveScript,同年12月,Netscape Navigator 2.0 Beta 3中部署时被重命名为JavaScript;
(2)1996年8月IE 3 发布,支持 jscript (微软实现的 js)
(3)1996年11月,网景向ECMA提交语言标准,由于版权问题,js 语言标准不叫 JavaScript,叫ECMAScript
(4)1997年6月,第一版ECMAScript发布
(5)1999年12月,第三版ECMAScript发布,这个版本使用最广(第四版没有发行成功)
(6)2006 年,jQuery 发布,它是目前最长寿的 js 库
(7)2009年12月,第五版ECMAScript发布,增加了一些功能
(8)2009 年,Ryan 基于 V8 (Chrome 的 js 引擎叫做 V8)创建了 Node.js
(9)2010年,Isaac基于node.js写出了npm
(10)2015年6月,第六版ECMAScript发布,新浏览器都支持这一版(之后每年发布一版,版本号以年份命 名)
JavaScript的兴起:需要一门语言可以直接运行在浏览器中,完成表单验证,减轻服务器的压力
ECMAScript5:编程(数据结构、逻辑控制、算法、内存分配、高级应用BOM-浏览器对象模型、DOM:应用程序API-文档对象模型)
早期主要运行在浏览器端,用于表单验证以及动画的实现。随着js版本的升级,现在的js可以运行在nodejs上,而nodejs又可以安装在绝大多数的操作系统中,所以js可以运行在绝大多数的系统中,除了完成表单验证以及动画的实现还可以进行服务器端编程,甚至于硬件编程。
JavaScript 的标准是 ECMAScript 。截至 2012 年,所有的现代浏览器都完整的支持 ECMAScript 5.1,2015年6月17日,ECMA国际组织发布了 ECMAScript 的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为 ECMAScript 6 或者 ES6。
需要注意的是,js不同于Java。Java是由sun公司开发并且维护,只能运行在jdk中。而js可以运行在绝大多数的浏览器中,主流浏览器就有IE、firefox、google chrome、safari…。那这样js的版本是不是就会有很多呢?如果这样,岂不是乱套了:程序员编写的js代码可以运行在firefox中,但是运行在IE中就会有问题。实际上,在早期确实有这样的问题,后来大家觉得这样搞下去会出问题,所以就坐在一起商量一套统一的语法,由于制定语法的这个组织叫ECMA,所以JavaScript的标准就是ECMAScript,这个ECMAScript中有哪些东西,实际上就是变量,表达式,关键字…的基础语法。
JavaScript是一个编程语言,允许用户在浏览器页面上完成复杂的事情。浏览器页面并不总是静态的,往往显示一些需要动态更新的内容,交互式地图,动画,以及视频等。一个完整的JavaScript包括核心(ECMAScript),应用程序编程接口即API (比如DOM(Document Object Model),BOM(Browser Object Model)),以及其他第三方API。JavaScript与HTML、CSS一同配合共同完成一个复杂页面的显示。
通常所说的JavaScript是应用在浏览器中,一般包括ECMAScript、DOM、BOM。ECMAScript为标准,DOM为浏览器提供的js操作html/css的js API,BOM为浏览器提供的js操作浏览器的js API。而JavaScript如果应用在nodejs中,则通常用于服务器端编程,可以进行io操作,网络操作等。
特点
客户端代码,在客户机上执行
1.JavaScript特殊的地方在于它也可以作为服务器端代码执行,但是需要搭建Node环境。node hello.js
2.在浏览器上运行
解释性语言
被内置于浏览器或者Nodejs平台中的js解析器解析执行,执行前无需编译
弱类型语言
从上往下顺序解析执行
系统环境
Linux 操作系统的环境*
Windows
MacOS
编辑器
vi、vim*
vscode/sumlime
运行环境
旧:JavaScript不能独立运行+网页+console/fireBug
nodejs*
调试:
火狐:firebug
console.log()/弹框alert
2. js组成
1) ECMAScrpt 【js标准】(兼容性100%) (类似于CoreJava,制定了基础的语法)
注释 // 、/**/
变量
操作符
流程控制语句
数组
对象
函数
正则表达式
…
所有的js解释器都可以兼容ECMAScript
2) DOM:Document Object Model文档对象模型
js操作html的api
是针对XML但经过扩展用于HTML的应用程序编程接口。DOM将整个页面映射成一个多节点结构。
var dom=document.getElementsByTagName(“input”);
var dom=document.getElementById(“input_name”);
dom.οnclick=function(){}
js语言:基础语法、基础库、扩展库(jQuery DOM库)
3) BOM:Browser Object Model 浏览器对象模型
js操作浏览器的api
开发人员可以使用BOM控制浏览器显示的页面以外的部分。弹出新浏览器窗口;移动,缩放,关闭浏览器的功能;提供浏览器详细信息的navigator对象;提供浏览器所加载页面的详细信息的location对象;提供用户显示器分辨率详细信息的screen对象;对cookies的支持;支持XMLHttpRequest,IE中的ActiveXObject自定义对象
alert()/prompt()/confirm()
setInterval(),setTimeout()
XMLHttpRequest
Ajax
这里需要注意的是,只有ECMAScript是标准,也就是在绝大多数浏览器以及js解析器(node)中运行效果相同,但是DOM与BOM是各大浏览器厂商自己提供的API,在使用上大同小异,但是也可能会出现少许不兼容的情况
js解释器:
1)浏览器厂商:Firefox(js标准)、IE(js)、Google(js)
兼容性:
JavaScript的三个组成部分,在当前五个主要浏览器(IE,Firefox,Chrom,Safari,Opera)中得到了不同程度支持,其中,所有浏览器对ECMAScript3支持大体都还不错,对ECMAScript支持程度越来越高,但对DOM的支持彼此相差较多,对已经正式纳入HTML5标准的BOM来说,尽管各浏览器都实现了某些众所周知的共同特性,但其他特性还因浏览器而异。
2)nodejs【网络编程(http模块)/数据库操作(mysql)/IO文件(file)】
http://nodejs.cn可以安装在linux windows macos unix等主流操作系统上
特征:可以运行在客户端、服务器端,解释性语言,弱类型语言,从上到下顺序执行。
在nodejs中,不存在兼容性问题,因为nodejs中压根就没有dom/bom,因此切记不要在nodejs中执行任何dom和bom代码,由于不存在兼容性问题,nodejs是可以大量发挥js高级标准,ES6语法一般在nodejs中可以完全运行。
js特点
- 解释型语言
js -> nodejs(js解释器)
- 弱类型语言
变量的数据类型取决于值的数据类型
var a ;
a = 2; // a的数据类型为number
a = true; // a的数据类型为boolean
- 顺序解释执行
- 既可以作为前端脚本语言,也可以作为后端语言,取决于应用平台(浏览器/操作系统)和使用的框架(dom、jquery/http、mysql、file)
在网页中使用JavaScript
内部JavaScript
编写好HTML,在<head>
标签体中添加<script>
元素,然后将js代码填写进来即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
alert('hello javascript')
</script>
</head>
<body>
</body>
</html>
在网页中使用JavaScript
外部JavaScript
单独新建一个后缀名为.js的js文件,编写好HTML文件,在<head>
标签体内添加<script>
元素,使用script标签的src属性将将js文件导入进来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="hello.js"></script>
</head>
<body>
</body>
</html>
在body和head中使用JavaScript的区别
在body部分中的JavaScript会在页面加载的时候被执行,在head部分中的JavaScript会在被调用的时候才执行。
因为浏览器解析html是从上到下的。如果把JavaScript放在head里的话,则先被解析,但这时候body还没有解析,所以会返回空值。一般都会绑定一个监听,当全部的html文档解析完之后再执行代码
windows.onload = function(){
// 这里放执行的代码
}
这就说明了,如果我们想定义一个全局对象,而这个对象是页面中的某个按钮时,我们必须将其放入body中,道理很明显:如果放入head,那当你定义的时候,那个按钮都没有被加载,可能获得的是一个undefind。一般习惯将JavaScript放在body的最后面,类似last-child。
在vi/vim中编写JavaScript
console.log('hello JavaScript')
使用node命令执行即可
$ node hello.js
注释
与绝大多数语言类似,JavaScript也需要注释来说明其代码含义,或者用来进行代码调试,注释后的代码会被浏览器忽略不被执行。
单行注释
// I am a comment
多行注释
/*
I am also
a comment
*/
3.关键字与保留字
关键字:(在js中有特殊功能)
break do try typeof
case else new var
catch finally return void
continue for switch while
debugger this function with
default if throw instanceof
delete in
保留字:(将来可能成为关键字)
abstract enum int short
boolean export interface static
byte extends long super
char final native synchronized
class float package throws
const goto private transient
debugger double implements protected
volatile import public
1) 区分大小写
typeof 关键字, typeOf 非关键字
2) 标识符
指变量,函数,属性的名字或者函数的参数。标识符是按照以下规则组合起来的一或多个字符:
1.字母,数字,下划线,$组成
2.只能以字母,下划线,$开头。
3.不能将关键字作为标识符。命名采用驼峰式命名
- 语句
每个语句以分号结尾,如果省略分号,由解析器确定语句的结尾,即分号可以省略,但是我们要求每个语句的末尾都应该有分号
4.变量
变量是一个值的容器,该容器的值可以随时改变。ECMAScript的变量是弱类型(松散类型),可以用来保存任何类型的数据。定义变量时使用var关键字。
变量的使用:
声明 var message;
初始化 message = “hello”
声明并初始化 var message = “hello”;
定义多个变量 var message= “hello”,found=false, age = 29;
变量名的命名规则:
变量名由字母,数字,下划线以及$组成。
不要使用下划线或者数字作为变量名的开头
变量名应该具有一定的意义,使用小驼峰命名规则 var userAgeTotal = “”;
不要使用关键字或是保留字
- 变量的使用
变量的使用一般用经过声明,初始化,使用三个步骤
// 变量声明
var a ;
// 变量初始化
a = 3;
// 变量调用
console.log(a);
- js是弱类型的语言
弱类型语言具有如下特点:
- 变量的数据类型在初始化的时候确定
- 变量的数据类型可以随时发生改变
- 类型细分不明显
- Java 是强类型语言
-
变量的数据类型在声明的时候确定
-
变量的数据类型一定确定不能更改
- var
var用于声明一个变量,在es6中,可以通过let声明一个变量,通过const声明一个常量
-
- 变量可以重复声明
var a = b = c = 3;
var d = 10,e = 20,f,g;
//弱类型语言,变量容器可以混合使用
var a = "hello world";//变量的重复赋值(相同的数据类型、不同的数据类型)
function a(){}
- 变量声明会被提升 (函数的声明也会)
//console.log(b);//报错
console.log(a);//不会报错
var a = 3;
//等价于:
var a;//在所有代码执行之前,js解释器会将js中所有的var声明的变量提升。
console.log(a);
a=3;
- var声明的变量的作用域
案例1
function foo(){
if(true){
var a = 3;
console.log("inner",a);//inner 3
}
console.log("outer",a);//inner 3 //没有块级作用域
}
foo();
console.log(a);//error! 函数作用域:局部作用域
// var 的变量声明提前知会提升到当前作用域的最前面
案例2
//如果在函数中定义变量没有加var,该变量为全局变量
function test(){
message = "hello";
}
test();
console.log(message); //可以访问
案例3
//用var操作符定义的变量将成为定义该变量的作用域中的局部变量
//全局作用域
function b() {
a = 10;
return;
}
var a = 1;
b();
console.log(a);//10
案例4
x = 1;//window.x global.x
console.log(x); //1
function y() {
console.log(x); //undefined
console.log(this.x);//1
var x = 2;
console.log(x); //2
}
y();
console.log(x);//1
案例5
//函数作用域:局部作用域
var a = 1;
function b() {
a = 10;
return;
//a函数声明,提前变量a,将a认为是函数b作用域的变量,具有局部效果
function a(){}
}
b();
console.log(a); // 1
5.数据类型
JavaScript基本数据类型:
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
JavaScript 拥有动态类型
JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型
var x; // x 为 undefined
var x = 5; // 现在 x 为数字
var x = "John"; // 现在 x 为字符串
字符串 String
字符串是存储字符(比如 “Bill Gates”)的变量。
字符串可以是引号中的任意文本。可以使用单引号或双引号:
var carname="Volvo XC60";
var carname='Volvo XC60';
可以在字符串中使用引号,只要不匹配包围字符串的引号即可:
var answer="It's alright";
var answer="He is called 'Johnny'";
var answer='He is called "Johnny"';
可以使用字符字面量,转义字符
\n 换行 \t 制表 \b 退格
\r 回车 \ 斜杠 ’ 单引号
" 双引号
字符长度可通过length属性获取字符长度
var str = "我是字符串";
console.log(str);
console.log(str.length);
var s4='\n\t\b\r';
数字 Number
JavaScript 只有一种数字类型。数字有很多类型,按照数字精度可以分为整数(int),单精度(float),双精度(double ),按照数字的表示方法可以分为二进制(Binary),八进制(Octal),十进制(decimal system),十六进制(Hexadecimal)。但是在js中,所有的数字统一使用Number来表示。
表示方法
整数:
十进制 55 由0~9组成
八进制 070 首位为0,其他位有0~7组成
十六进制 0x11 首位为0x,其他位为09,AF
var num1 = 34; //不使用小数点来写
var num2 = 010; //8
var num3 = 0x10; //16
console.log(x1, x2, x3, x4);
浮点数:
所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后必须至少有一位数字。浮点数值的最高精度是17位小数
普通浮点数 3.1415926
科学计数法 3.125e7 即31250000
var f1 = 3.1415926; //3.1415926
var f2 = 3.125e7; //31250000
console.log(f1, f2);
非数值:
该数值表示一个本来要返回数值的操作数未返回数据的情况
var a = 10/ "a"; // a为NaN
非数值检测:
判断参数是否“不是数值”,当参数para不是数值的时候返回true
isNaN(NaN); // true
数值范围:
由于内存的限制,ECMAScript不能保存世界上所有的数值。
ECMAScript能表示的最小数值保存在Number.MIN_VALUE中
能表示的最大的数值保存在Number.MAX_VALUE中。
如果某次计算的结果超过了JavaScript数值范围,将会返回Infinity(正无穷)或者-Infinity(负无穷)
var a = 9/0; // Infinity
Number.MIN_VALUE 5e-324
Number.MAX_VALUE 1.7976931348623157e+308
数值范围检测:
使用 isFinite()函数可以判断参数是否在最大值和最小值之间,如果在,返回true
var a = isFinite(9/0); // false
布尔 Boolean
布尔(逻辑)只能有两个值:true 或 false。
var x=true;
var y=false;
Null
该类型的取值只有一个,即null。null可以表示一个空对象的指针。
var a = null;
如果一个变量准备将来保存对象,可以将该变量初始化null而不是其他,这样可以通过检查null值就可以知道
相应的变量是否已经保存了一个对象的引用。
if(car !== null ){ //car对象执行某些操作}
Undefined
Undefined 这个值表示变量不含有值。未定义的。
var a;
console.log(a,typeof a);//undefined 'undefined'
var a = undefined;
console.log(a,typeof a);//undefined 'undefined'
undefined 与null关系
undefined继承null,所以undefined == null结果为true,但是null表示空对象,undefined表示未定义;
null与undefined用途不同,null可以用来表示一个空对象,但是没有必要把一个变量的值显式设置为undefined。
//null vs undefined
console.log(undefined == null); //true //undefined派生自null
console.log(undefined === null);//false
if(null == undefined){console.log('相等的')}
if(null === undefined){console.log('完全相等')}
// ==, 等同 的意思, 两边值类型不同的时候,要先进行类型转换为同一类型后,再比较值是否相等。
// ===,恒等 的意思, 不做类型转换,类型不同的结果一定不等。
// "=="表示只要值相等即可为真,而"==="则要求不仅值相等,而且也要求类型相同。
// 建议:尽量使用严格运算符 ===。因为"=="不严谨,可能会带来一些违反直觉的后果。
引用数据类型
在js中除了以上基本数据类型,其他所有类型都可以归结为引用数据类型。
对象Object
对象是模拟现实生活的对象,对象由键值对组成,通过使用大括号将所有键值对括起来。
var dog = {
name: 'momo',
age: 4
}
可以通过点语法获取对象的属性
dog.name; //momo
dog.age; //age
数组Array
数组是一个特殊的对象,包含了多个值,值与值之间使用逗号分隔开,所有的值通过中括号括起来。
var classArr = ['web2104','web2105','web2106']
var studentArr = ['zhangsan','lisi','wangwu']
可以通过数组下标获取对应的数据
classArr[0]; // web2104
函数Function
函数是代码执行单元,用于实现某些特殊的功能。
function sum(a, b) {
return a + b;
}
//执行函数
sum(1,2); // 3
基本数据类型和引用数据类型在内存中如何存储
基本数据类型变量都维护在栈区,基本数据类型的值保存在栈区。
例如:
var a = 123;
b = a;
a = 456;
1.var a = 123; b = a;基本数据类型是在栈内存中存储的,如下图,b = a的时候,b直接把a的值存进去
2.a = 456; 会把a的值改为456,但是对b没有任何影响,所以最后会输出a = 456;b = 123;
结论:基本数据类型的值存在栈,值与值之间独立存在,修改一个值不会影响其他变量
引用数据类型的引用地址保存在栈区,值保存在堆区。
例如:
var obj = {
name: 'zhangsan'
}
var obj1 = obj; //将对象obj赋值给对象obj1
console.log(obj.name); //zhangsan
console.log(obj1.name); //zhangsan
// 修改obj的name
// 当obj属性name变为"lisi"时,obj1属性name也变为"lisi"
obj.name = 'lisi';
console.log(obj.name); //lisi
console.log(obj1.name); //lisi
结论:当栈存放引用类型时,值为对象的地址,obj与obj1指向同一个地址,所以当obj的name值变为“lisi”时,obj1也会发生变化
主要针对于引用数据类型参数说的,浅拷贝表示仅拷贝引用地址,深拷贝表示对于对象的克隆。
实现深拷贝的方法
- 通过json对象实现深拷贝(JSON.stringify,JSON.parse)
- Object.assign()拷贝
- lodash函数库实现深拷贝
- 递归的方式实现深拷贝
- 等等
6. 类型判断
在实际开发中,我们经常要判断一个变量的数据类型。
- typeof
使用typeof判断数据类型
返回该变量名所指向数据的类型
语法: typeof 变量名
返回值如下:
“undefined” 未定义
“boolean” 布尔类型
“string” 字符串
“number” 数值
“object” 对象或者null或者数组
“function” 函数
通过typeof可以判断一个变量的类型
var a = 3;
typeof a; // number
if((typeof a) == "string"){}
if(a == "null"){}
if(a == null){}
- isNaN
判断是否是 不是一个数字
var a = 10/'a';
isNaN(a); //true
- isFinite
判断是否是一个有效值
var a = 10/0 ;
isFinite(a) // false