JS

JavaScript介绍

ECMAScript和JavaScript的关系

1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这门语言能够成为国际标准。次年,ECMA发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript,这个版本就是1.0版。

该标准一开始就是针对JavaScript语言制定的,但是没有称其为JavaScript,有两个方面的原因。一是商标,JavaScript本身已被Netscape注册为商标。而是想体现这门语言的制定者是ECMA,而不是Netscape,这样有利于保证这门语言的开发性和中立性。

因此ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现。

ECMAScript的历史

年份 名称 描述
1997 ECMAScript 1 第一个版本
1998 ECMAScript 2 版本变更
1999 ECMAScript 3 添加正则表达式添加try/catch
ECMAScript 4 没有发布
2009 ECMAScript 5 添加"strict mode"严格模式添加JSON支持
2011 ECMAScript 5.1 版本变更
2015 ECMAScript 6 添加类和模块
2016 ECMAScript 7 增加指数运算符(**)增加Array.prototype.includes

ES6就是指ECMAScript 6。

尽管 ECMAScript 是一个重要的标准,但它并不是 JavaScript 唯一的部分,当然,也不是唯一被标准化的部分。实际上,一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:

  • 核心(ECMAScript)
  • 文档对象模型(DOM) Document object model (整合js,css,html)
  • 浏览器对象模型(BOM) Broswer object model(整合js和浏览器)

简单地说,ECMAScript 描述了JavaScript语言本身的相关内容。

JavaScript 是脚本语言
JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

JavaScript 很容易学习。

javaSrcipt引入方式

我们可以像添加 CSS 那样将 JavaScript 添加到 HTML 页面中。CSSlink使用元素链接外部样式表,使用style 元素向 HTML 嵌入内部样式表,JavaScript 这里只需一个元素script

内部Javascript

首先,新建index.html。放在一个文件中

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    //编写Javascript代码
</script>
</body>
</html>

外部Javascript

  1. 首先,在刚才的html文件所在的目录下创建一个名为script.js的新文件。请确保文件扩展名为.js,只有这样才能被识别为Javascript代码。

  2. srcipt元素替换为

    <script src="script.js" async></script>
    
  3. 在script.js文件中,就可以编写Javascript代码

Javascript语句和注释

JavaScript语句

在前言篇中,我们了解到Javascript代码最终是被浏览器解释运行的,可以简单的认为这些语句是发给浏览器的一些指令。这些指令的作用是告诉浏览器要做的事情。

每一句Javascript代码都以;作为结束当前语句。

注释

跟HTML和CSS一样,在JS中也会用到注释。它的高效使用可以提高代码的可读性,帮助自己和别人阅读和理解您所编写的Javascript代码。注释可分为单行注释多行注释两种。

单行注释

在JS中以//凯欧知道行末的字符被视为行注释,注释是给开发人员看的,Javascript引擎在执行JS代码的时候回自动忽略。

多行注释

另一种注释使用/**/把多行字符包裹起来,把一大视为一个注释

变量

从编程角度讲,变量是用于存储某种/某些数值的容器。我们可以把变量看作一个纸箱子。为了区分纸箱子,可以用AB名称代表不同的盒子。A和B就是盒子的名字(也就是变量的名字)。A中可以存储渣渣辉,B中可以存储45

声明变量

如果我们使用纸箱子装东西,是不是先要找到纸箱子,那在JS中要想使用纸箱子(变量),你需要做的是先把它造出来——更准确的说,要声明一个变量(找到纸箱里)。声明变量使用关键字var,语法如下

var 变量名;

var就相当于找纸箱子的动作。

变量名可以任意取名,但要遵循命名规则

  1. 变量必须使用字母、下划线(_)或者美元符($)开始。
  2. 可以使用任意多个英文字母、数字、下划线()或者美元符($)组成。
  3. 不能使用Javascript关键字和Javascript保留字来进行命名
  4. 变量名严格区别大小写,如A何a是两个不同的变量

保留字

abstract boolean byte char class
debugger double enum export extends
final float goto implements import
int interface long native package
private protected public short static
super synchronized throws transient volatile
const

当然,既然我们可以一个一个的找纸箱子,也可以一次性的找多个纸箱子,所以var还可以一次声明多个变量,变量之间用,逗号隔开。

var x, y, z;

变量赋值

我们可以把变量看作一个纸盒子,盒子用来存放物品,那如何在变量中存储内容呢?

我们可以使用"="等号给变量存储内容

var x = 5; //声明变量x并将5赋值给x

也可以这样写

var x; //声明变量x
x = 5; //给变量x赋值

注意: 这里的=号的作用是给变量赋值,不是等于号

更新变量

变量可以看作一个纸盒子,盒子中可以存储物品,那我也可以去更改存储的物品。同样,一旦变量赋值,我们也可以给它一个不同的值来更新它。如:

var x = 5;
x = 10;

数据类型

计算机顾名思义就是可以做数学计算的机器。因为,计算机程序理所应当然地可以处理各种数值。但是,计算机能处理的远远不止数值,它可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。

Number(数值)

你可以在变量中存储数字,无论这些数字是像30(整数)这样,或者像1.234这样的小数(浮点数)。Javascript不区分整数和浮点数,统一用Number表示。与其它编程语言(Javas)不同的是在JS中你不需要声明一个变量的类型。比如这样都是合法的:

var x = 123;
var y = 1.213;
var z = -99;

String(字符串)

字符串是文本的一部分。当你给一个变量赋值给字符串时,你需要用单引号或双引号把值包括起来。

var name1 = 'asd';
var name2 = "abc";

单引号和双引号应用的字符串没有任何区别

字符串常用方法

方法 说明
.length 返回长度
.trim() 移除空白
.trimLeft() 移除左边的空白
.trimRight() 移除右边的空白
.charAt(n) 返回第n个字符
.concat(value, ...) 拼接
.indexOf(substring, start) 子序列位置
.substring(from, to) 根据索引获取子序列
.slice(start, end) 切片
.toLowerCase() 小写
.toUpperCase() 大写
.split(delimiter, limit) 分割

Boolean(布尔值)

区别于python, true和false都是小写

var a = true;
var b = false;

(空字符串)、0、null、undefined、NaN都是false。

null和undefined

  • null表示值是空,一般在需要指定或清空一个变量时才会使用,如 name=null;
  • undefined表示当声明一个变量但未初始化时,该变量的默认值是undefined。还有就是函数无明确的返回值时,返回的也是undefined。

数字和运算符

算数运算符

运算符 名称 作用 示例
+ 加法 两个数相加。 6 + 9
- 减法 从左边减去右边的数。 20 - 15
* 乘法 两个数相乘。 3 * 7
/ 除法 用右边的数除左边的数 10 / 5
% 求余(有时候也叫取模) 在你将左边的数分成同右边数字相同的若干整数部分后,返回剩下的余数 8 % 3 (返回 2,将8分成3份,余下2 。)

递增和递减运算符

var x = 2;
x++;//相当于x = x + 1;

赋值运算符

赋值运算符是向变量分配值的运算符。比如:

var x = 3;//将3赋值给变量x
var y = 4;//将4赋值给变量y
x = y; //将变量y的值赋值以定义的变量x,那么变量x重新赋值。x和y有相同的值,4

但是还有一些更复杂的类型,他们提供了有用的快捷方式,可以使您的代码更加清洁和高效。

var x = 3;
x = x + 4;
//可以简写成
var x = 3;
x += 4;//等价于 x = x + 4;

常见的如下:

运算符 名称 作用 示例 等价于
+= 递增赋值 右边的数值加上左边的变量,然后再返回新的变量。 x = 3;x += 4; x = 3;x = x + 4;
-= 递减赋值 左边的变量减去右边的数值,然后再返回新的变量。 x = 6;x -= 3; x = 6;x = x - 3;
*= 乘法赋值 左边的变量乘以右边的数值,然后再返回新的变量。 x = 2;x *= 3; x = 2;x = x * 3;
/= 除法赋值 左边的变量除以右边的数值,然后再返回新的变量。 x = 10;x /= 5; x = 10;x = x / 5;

数组

数组对象的作用是:使用单独的变量名来存储一系列的值。类似于Python中的列表。

var a = [123, "asd"];
consloe.log(a[1]); // 在控制台输出"asd"

访问和修改数组元素

  1. 因为数组中的每个元素都有索引值的,所以我们可以通过索引值来获取对应的元素值。

    a[0];//123
    
  2. 通过新值来修改数组中的元素。例如:

    a[0] = 456;
    console.log(a);//[456,"asd"];
    
  3. 数组中包含数组的话称之为多维数组。你可以通过将两组方括号链接在一起来访问数组中的另一个数组。

获取数组的长度

可以通过使用length属性获取数组的长度(查看数组有多少个元素)。

a.length;//2

尾部追加元素

a.push("ddd");//[456,"asd","ddd"]

常用方法:

方法 说明
.length 数组的大小
.push(ele) 尾部追加元素
.pop() 获取尾部的元素
.unshift(ele) 头部插入元素
.shift() 头部移除元素
.slice(start, end) 切片
.reverse() 反转
.join(seq) 将数组元素连接成字符串
.concat(val, ...) 连接数组
.sort() 排序
.forEach() 将数组的每个元素传递给回调函数
.splice() 删除元素,并向数组添加新元素。
.map() 返回一个数组元素调用函数处理后的值的新数组

流程控制

if...else

条件判断

javascript中最常见到的语句

if(有钱的话){
    买车;
}else{
    买房;
}
  1. 关键字if,并且后面跟随括号。
  2. 测试的条件,放到括号里(通常是“这个值大于另一个值吗”或者“这个值存在吗”)。这个条件会利用比较运算符我们会在最后的模块中讨论)进行比较,并且返回true或者false。
  3. 一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且只会在条件语句返回true的时候运行。
  4. 关键字else
  5. 另一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且当条件语句返回值不是true的话,它才会运行。

这段代码真的非常易懂——它说“如果(if)条件(condition)返回true,运行代码A,否则(else)运行代码B”

注意: 不一定必须写else和之后的第二个花括号

if(可以的话){
    //我要谈女朋友
}
//不可以谈女朋友

不过,这里你需要注意——在这种情况下,第二段代码不被条件语句控制,所以它总会运行,不管条件返回的是true还是false。这不一定是一件坏事,但这可能不是你想要的——你经常只想要运行一段代码或者另一段,而不是两个都运行。

最后,有时候你可能会看到 if…else 语句没有写花括号,像下面的速记风格:

if (可以的话) 
    可以谈女盆友;
else 
    不可以谈女朋友;

这是完全有效的代码,但不建议这样使用——因为如果有花括号进行代码切割的话,整体代码被切割为多行代码,更易读和易用。

else if

多个选择和结果

例:

var weather = 'sunny';
if(weather == 'sunny'){
    //天气非常棒,可以出去玩耍了
}else if(weather == 'rainy'){
    //天气下雨了,只能在家里呆着
}else if(weather == 'snowing'){
    //天气下雪了,可以出去滑雪了
}

switch

多个if...else嵌套可以用switch

if...else 语句能够很好地实现条件代码,但是它们还是有缺点的。 它们主要适用于您只有几个选择的情况,每个都需要相当数量的代码来运行,和/或 的条件很复杂的情况(例如多个逻辑运算符)。 对于只想将变量设置一系列为特定值的选项或根据条件打印特定语句的情况,语法可能会很麻烦,特别是如果您有大量选择。

语法:

switch (expression) {
  case choice1:
    run this code
    break;
  case choice2:
    run this code instead
    break;
  default:
    actually, just run this code
}
  1. 关键字 switch, 后跟一组括号.
  2. 括号内的表达式或值.
  3. 关键字 case, 后跟一个选项的表达式/值,后面跟一个冒号.
  4. 如果选择与表达式匹配,则运行一些代码.
  5. 一个 break 语句, 分号结尾. 如果先前的选择与表达式/值匹配,则浏览器在此停止执行代码块,并执行switch语句之后的代码.
  6. 你可以添加任意的 case 选项
  7. 关键字 default, 后面跟随和 case 完全相同的代码模式 (选项 3–5), except that default之后不需要再有选项, 并且您不需要 break 语句, 因为之后没有任何运行代码. 如果之前没有选项匹配,则运行default选项.

例:

var weather = 'sunny';
switch(weather){
    case 'sunny':
        //天气非常棒,可以出去玩耍了
        break;
    case 'rainy':
       //天气下雨了,只能在家里呆着
        break;
    case 'snowing':
        //天气下雪了,可以出去滑雪了
        break;
    default:
        //哪里也不出去
}

三元运算符

三元运算符它解决了像if..else块较少的代码。如果你只有两个通过true/false条件选择。语法如下:

(codition) ? run this code : run this code instead;

例:

var a = 1;
var b = 2;
var c = a > b ? a : b
//这里的三元运算顺序是先写判断条件a>b再写条件成立返回的值为a,条件不成立返回的值为b;三元运算可以嵌套使用;

for循环

Javascript的循环有两种,一种是for循环,通过初始化条件结束条件递增条件来循环执行语句块,语法如下:

for(初始化条件;结束条件;递增条件){
    //run this code
}

例:

//计算1到10000之间的数的和
var total = 0;
var i;
for(i = 1;i <= 10000;i++){
    totle = totle + i;
}
console.log(totle);//50005000

分析:

  • i = 1,这是初始条件,将变量i设置为1
  • i<=10000这是判断条件,满足时就继续循环,不满足则退出循环
  • i++ 这是最后循环后的递增条件,由于每次循环后变量i都会+1。因为它终将在若干次循环后不满足判断条件i<=10000则退出循环

for用于遍历数组

for循环最常用的地方是利用索引来遍历数组:

var shopping = ['香蕉','苹果','牛奶','红牛'];
var x;
for(var i = 0; i < shopping.length; i ++){
    x = shopping[i];
    console.log(x);
}

break退出循环

for循环的3个条件都是可以省略的,如果没有退出循环的判断条件,就必须使用break语句退出循环,否则就是死循环:

var x = 0;
for (;;) { // 将无限循环下去
    if (x > 100) {
        break; // 通过if判断来退出循环
    }
    x ++;
}

continue语句

continue语句中断循环中的迭代,如果出现了指定的条件,然后继续循环中的下一个迭代。

var x;
for(var i = 0; i <= 10; i++){
    if(i == 3) continue;
     x = x + "这个数字是" + i 
}

break和continue的区别

看完上面两个语句的介绍,两者的区别应该很清晰了,可以说没必要继续看下面的。

如果还有一点点的疑惑,下面再来用通俗的语言做一下描述。

假设有皇帝要选美女,那么这时候循环语句开启,美女挨个让皇帝过目。

break陛下,不贪心,选中一个美女之后,就终止了选美。

continue陛下,可能比较贪心,选中以后,喊了一句“下一个”,也就是继续循环的进行。

while循环

for不是javaScript中唯一可用的循环类型。for循环在已知循环的初始和结束条件时非常有用。而上述忽略了条件的fox循环容易让人看不清循环的逻辑。此时在Javascript中的另一种循环则是while循环,使用它最佳。

while循环只有一个判断条件,条件满足,就不断循环,条件不满足则退出循环。

语法:

初始化条件
while(判断循环结束条件){
    //code to run
    递增条件
}

例:

//计算100以内所有奇数之和
var x = 0;
var n = 99;
while (n > 0) {
    x = x + n;
    n = n - 2;
}
x;//2500

在循环内部变量n不断自减,直到变为-1时,不再满足while条件,循环退出。

do...while循环

最后一种循环是do { ... } while()循环,它和while循环的唯一区别在于,不是在每次循环开始的时候判断条件,而是在每次循环完成的时候判断条件:

var n = 0;
do {
    n = n + 1;
} while (n < 100);
n; // 100

do { ... } while()循环要小心,循环体会至少执行1次,而forwhile循环则可能一次都不执行。

函数

什么是函数

在Javascript中另一个基本概念是函数,它允许你在一个代码块中存储一段用于处理一个任务的代码,然后在任何你需要的时候用一个简短的命令来调用,而不是把相同的代码写很多次。

比如我们要完成多数组和的功能

var sum;
sum = 3 + 2;
console.log(sum);
sum = 7 + 8;
console.log(sum);
... //不停重复两行代码

如果想实现8组数的和,就需要16行diamante,实现的越多,代码行也就越多。这个时候我们把完成特地功能的代码块放到一个函数里,直接调用该函数,就省去了重复输入大量代码的麻烦。

由此可见,函数的作用,可以写一次性代码,然后反复的重用这个代码。

代买:

var sum = 0;
//只需要编写一次
function sum(a,b){
    sum = a + b;
    console.log(sum);
}
sum(3,2);
sum(5,6);
sum(8,10);
...//只需调用函数即可

定义函数

一个函数定义(也称为函数声明,或函数语句)由一些列的function关键字组成。例如,以下代码是一个简单的计算多组数的和的函数,我们给它命名为sum

function sum(a,b){
    //函数体;
}
  • function为函数的关键字
  • sum为函数的名称
  • sum后面跟随的()中的内容叫函数参数列表,a和b用逗号隔开
  • 定义函数的Javascript语句,用大括号{}括起来。

函数的调用

函数定义好后,它是不能自动执行的,需要调用它,直接在需要的位置写函数名。

function sum(a,b){
    console.log(a+b);
}
sum(3,5);//调用函数,直接写函数名

我们把定义函数时传入的两个参数a和b叫形参(形式参数,一个将来被代替的参数),调用函数时传入的两个参数叫实参(实际的参数)。

如果向在定义函数时添加多个形参。可以在后面添加多个,注意参数之间用逗号隔开

函数的返回值

我们在计算两个数之和的时候,可以给函数一个返回值,每次调用该函数,你就能计算出两个数之和。

function sum(a,b){
    return a+b
}
var result = sum(4,5);

通过在函数体中return关键字 将计算的结果返回,调用函数之后你会得到该返回值,并用变量result接收。

函数表达式

虽然上面的函数定义在语法上是一个语句,但函数可以由函数表达式创建。这样的函数可以是匿名的;它不必有一个名称。例如,函数sum也可以这样去定义:

var sum = function(a,b){
    return a + b;
}
sum(4,5);

但是这种方式只会令人费解,所以我们不要这样做!创建功能时,最好只要坚持第一种函数定义的方式就可以。

函数的作用局和冲突

处理函数时,作用域是非常重要的一个概念。当你创建函数时,函数内定义的变量和其它东西都在它们自己的单独的范围内,意味着它们被锁在自己独立的房间内。

所有的函数的最外层被称为全局作用域。在全局作用域内定义的值可以任意地方访问。

Javascript主要是由于安全性和组织性。有时不希望变量可以在代码中的任何地方访问。

例如,假设你有一个HTML文件,它调用两个外部的Javascript文件,并且他们都有一个相同的名称定义的变量和函数:

<!-- my HTML file -->
<script src="first.js"></script>
<script src="second.js"></script>
<script>
  hello();
</script>
//first.js
var name = 'Tom';
function hello() {
  alert('Hello ' + name);
}
//second.js
var name = 'Jack';
function hello() {
  alert('Hello ' + name);
}

这两个函数都是用hello()形式调用,但是你只能访问到 second.js文件的hello()函数。second.js 在源代码中后应用到HTML中,所以它的变量和函数覆盖了 first.js 中的。我们称为这种行为叫代码冲突

将代码锁定在函数中避免了这样的问题,并能解决我们代码冲突的问题。

例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Function scope example</title>
    </head>
    <body>
        <script>
            var x = 1;
            function a() {
                var y = 2;
            }
            function b() {
                var z = 3;
            }
            function output(value){
                return value;
            }
            console.log(output(x)); // 1
            console.log(output(y)); // Uncaught ReferenceError: y is not defined
            console.log(output(z)); // Uncaught ReferenceError: z is not defined
        </script>
    </body>
</html>

后面两个都应该返回错误,这是为什么?由于函数作用域,y和z被锁定在函数a()b()函数中,所以output()从全局作用域调用时无法访问他们。

但是,从另一个函数里面调用呢?

function a() {
    var y = 2;
    output(y);
}
function b() {
    var z = 3;
    output(z);
}
function output(value){
    return value;
}
a();
b();

打印出对应的结果。这样是没有问题的,因为output()函数在其他函数的内部被调用。在这种情况下,输出变量的定义和函数的调用都在同一个作用域中(注:即函数作用域)。output()它可以在任何地方被调用,因为它在全局作用域中被定义。

修改你的代码如下,如下所示:

function a() {
  var y = 2;
  output(x);
}
function b() {
  var z = 3;
  output(x);
}
a();
b();

函数 a()b()都应该输出x—-1的值。这些没有问题,因为即使output()的调用与x的定义不在同一个作用域内,但x是一个全局变量,所以在所有代码中都可用。

注意:相同的范围规则不适用于循环(for(){…})和条件块(if(){…}) - 它们看起来非常相似,但它们不一样!小心不要让这些困惑。

注意:ReferenceError:“x”未定义错误是您遇到的最常见的错误。如果您收到此错误,并且确定您已经定义了该问题的变量,请检查它的范围。

函数内的函数

在任何地方你都可以调用函数,甚至可以在另一个函数中调用函数。这通常被用作保持代码整洁的方式。如果你有一个复杂的函数,如果将其分解成几个子函数,它更容易理解:

function myBigFunction() {
  var myValue;
  subFunction1();
  subFunction2();
  subFunction3();
}
function subFunction1() {
  console.log(myValue);
}
function subFunction2() {
  console.log(myValue);
}
function subFunction3() {
  console.log(myValue);
}

只需确保在函数内使用的值正确的范围. 上面的例子会抛出一个错误ReferenceError:MyValue没有被定义,因为尽管myValue变量与函数调用的作用域相同, 但在函数定义内没有定义 - 调用函数时运行的实际代码。为了使这个工作,你必须将值作为参数传递给函数,如下所示:

function myBigFunction() {
  var myValue = 1;
  subFunction1(myValue);
  subFunction2(myValue);
  subFunction3(myValue);
}
function subFunction1(value) {
  console.log(value);
}
function subFunction2(value) {
  console.log(value);
}
function subFunction3(value) {
  console.log(value);
}

全局变量和局部变量

局部变量

在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它(该变量的作用域是函数内部)。只要函数运行完毕,本地变量就会被删除。

全局变量

在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。

变量生存周期

JavaScript变量的生命期从它们被声明的时间开始。

局部变量会在函数运行以后被删除。

全局变量会在页面关闭后被删除。

posted @ 2019-10-23 22:34  極9527  阅读(208)  评论(0编辑  收藏  举报