写点什么

JavaScript 基础语法知识遨游记

作者:未见花闻
  • 2022 年 6 月 18 日
  • 本文字数:7140 字

    阅读完需:约 23 分钟

1.JS 简介

JavaScript 一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML(标准通用标记语言下的一个应用)网页上使用,用来给 HTML 网页增加动态功能。

在 1995 年时,由 Netscape 公司的 BrendanEich,在网景导航者浏览器上首次设计实现而成。因为 Netscape 与 Sun 合作,Netscape 管理层希望它外观看起来像 Java,因此取名为 JavaScript。但实际上它的语法风格与 Self 及 Scheme 较为接近。

为了取得技术优势,微软推出了 JScript,CEnvi 推出 ScriptEase,与 JavaScript 同样可在浏览器上运行。为了统一规格,因为 JavaScript 兼容于 ECMA 标准,因此也称为 ECMAScript。


JavaScript (简称 JS)


  • 是世界上最流行的编程语言之一

  • 是一个脚本语言, 通过解释器运行

  • 主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行


JavaScript 的能做的事情:


  • 网页开发(更复杂的特效和用户交互)

  • 网页游戏开发

  • 服务器开发(node.js)

  • 桌面程序开发(Electron, VSCode 就是这么来的)

  • 手机 app 开发


JavaScript 之父 布兰登·艾奇 (Brendan Eich)


JavaScript 诞生前:



JavaScript 诞生后:



JavaScript 和 HTML 和 CSS 之间的关系:


  • HTML: 网页的结构(骨)

  • CSS: 网页的表现(皮)

  • JavaScript: 网页的行为(魂)


2.JS 基本知识

2.1 如何在 HTML 页面中使用 JS

主要包括内嵌式,行内式,外部式三种方式,最推荐的那当然就是外部式,如果 js 代码比较简单,可以使用内嵌式,如果非常简单可以使用行内式。在 js 中单行注释使用//来表示,/**/表示多行注释,此外,js 不区分单双引号,并且每个语句后面的分号可以不写。


2.2 第一个 js 程序

前面说那个 HTML 中button标签的时候,搭配使用了alert语句,这个其实就是 js 中的代码,采用了行内式的形式,那这就是我们 js 的第一个程序了。


<button onclick="alert('hello js')">点击进入第一个js程序</button>
复制代码



当然可以另起一个 js 文件使用外部引用的方式来执行 js 代码。


<script src="./hello.js"></script>
复制代码


//hello.jsalert("hello js!");//js中单双引号不分家
复制代码


内嵌式也是可以的


    <script>        // 这是js注释        alert("hello js");    </script>
复制代码



如果一个元素中有多个 alert 语句,只有外层的 alert 会起作用。


    <script src="./hello.js">        // 这是js注释        alert("hello inner js");    </script>
复制代码


//hello.jsalert("hello js!");//js中单双引号不分家
复制代码



使用 alert 显示弹窗提示是一种很常见的交互方式,但是使用 js 来进行输出,使用 console.log 更为常见。毕竟使用弹窗了打印,毕竟比较烦,用户看了体验也很不好。在浏览器开发者工具中,有一个控制台,在这个控制台上就能使用 js 的输出语句,看到输出的内容,如果出现了语法错误控制台上也会有提示。


    <script>        console.log("hello js log");    </script>
复制代码


2.3 变量

语法格式:


var 变量名 = 值;
复制代码


与 java/c/c++不同的是,这个var类型的变量可以接收多种类型的变量值,它可以是int,它可以是double,它可以是字符串,它还可以是数组,甚至它可以是函数变量(类似与 C 语言中的函数指针)。


var a = 10;a = 22;console.log(a);
复制代码


输出结果:


22
复制代码


var 变量(其实不止 var 变量是这样,如 let 变量也是这样)在没有初始化值的时候,是一个特殊的值undefined


var a;console.log(a);
复制代码


输出结果:


undefined
复制代码


如果变量被赋予其他的值,其类型会随着修改的值而改变,比如数字变成字符串类型。


var b = 10;b = "hello";console.log(b);
复制代码


输出结果:


hello
复制代码


像这种在运行时,变量类型随着值的变化而变化的类型称为动态类型,显然 java8 是不支持的,java 是静态类型,不过像 Python,PHP 等语言和 js 一样,都是动态类型。虽然动态类型相比于静态类型更加的灵活,但是在编译检查方面,静态类型可以更好地检查,而动态类型检查不是很严格,这也就导致当代码出现问题时,静态类型的代码更容易找出错误,综合来看,静态类型还是要好一点的。


除了 var 类型,let 类型也能够起到同样的效果,其实 var 类型是早期的版本,在作用域这一方面与我们所想的不同,比如在我们所理解的作用域外面,它还能够被访问,而 let 就优化了这一点。


{    var a = 100;    let b = 100;}console.log("var:");console.log(a);console.log("let:");console.log(b);
复制代码


输出结果:


2.4js 内置的类型

  • [ ] number,表示数字。

  • [ ] boolean,表示真假,非 0 为真,0 为假。

  • [ ] String,字符串。

  • [ ] undefined,表示未定义。

  • [ ] null,表示空值。

  • [ ] NaN,表示非数字值,一般字符串与数字进行非加法运算会出现,为什么加法不会出现,因为+也能表示字符串拼接,可以使用 isNaN 函数来判断计算结果是否是 NaN。

  • [ ] Infinity,无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围。

  • [ ] -Infinity,负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围。

2.4.1 数字

js 中数字,包括整数,浮点数等,对于数字,同样 js 与 java 一样,支持二进制,八进制,十六进制的表示。


let a = 066;//八进制let b = 0x2f6;//十六进制let c = 0b10101;//二进制
复制代码

2.4.2 字符串

字符串的拼接:使用+运算符进行拼接。


let s = "hello";let a = 64;console.log(s+a);
复制代码


输出结果:


hello64
复制代码


求字符串的字符个数:使用变量名.lenght就能够获取到字符串的长度。


let s = "hello string";console.log(s.length);
复制代码


输出结果:


12
复制代码


除了这些,字符串还能进行切割等,和 java 差不多就不多说了。


当然还有转义字符也是支持的,比如\n回车,\t制表等都是一样支持的。

2.4.3 布尔类型

这个很简单,true表示真,false表示假,它与 C 语言一样,非 0 为真,0 为假,与 java 不同,除此之外,js 的布尔类型支持与数字运算,而 java 是不能的,运算时,true表示1false表示0


let a = true;let b = false;
console.log(a + 10);//11console.log(b + 10);//10console.log(a + b);//1
复制代码

2.4.4undefined 类型与 null 类型

只有 undefined 这一个值,表示变量处于为初始化的状态,其实是属于非法的情况。它与 null 不同,null 表示变量初始化了,但值为null

2.5 运算符

js 的运算符与其他语言的运算符基本上一模一样,就不多说了。


但是还是有不同的部分的,主要就是比较相等的运算符。==!=:表示比较两个变量的值是否相等。===与·!==:表示比较变量的值与类型是否相等。


let a = 10;let b = "10";
console.log(a == b);//trueconsole.log(a === b);//false
复制代码


逻辑运算符也和其他语言有区别,区别主要在运算返回的值并不是 true 和 false,这个值到底是什么,其实与短路效应是有关的。&&:表示且,比如 a&&b,如果表达式 a 为假,则结果为 a 的值,如果表达式 a 为真,则结果为 b 的值。||:表示或,比如 c||d,如果表达式 c 为真,则结果为 c 的值,如果表达式 c 为假,则结果为 d 的值。


let x = null;if (x == null) {    x = 0;} //相当于 x = x || 0;
复制代码

2.6 条件语句

与其他语言差不多,if...else if...else 语句。其中 else if 语句可以没有,可以有一个也可以有多个,else 语句可以有也可以没有,代码块只有一条时,大括号建议也写上。


if (表达式1) {  //代码块} else if (表达式2) {  //代码块}... {
} else { //代码块}
复制代码


还有我们非常熟悉的 switch 老朋友,基本格式如下:


switch (表达式) {  case 值1:    语句1;    break;  case 值2:    语句2;    break;  ...  default:    语句n;    break;}
复制代码


个人建议不要省略break,不然可能会发现执行了多个 case 的语句哦。

2.7 循环语句

for 循环:


for (表达式1; 表达式2; 表达式3) {  语句体;}
复制代码


表达式 1:用来定义,初始化变量,一个循环只执行一次。表达式 2:循环条件,为true执行语句块,为false循环结束。表达式 3:变量自增,赋值。


执行顺序,表达式 1->表达式 2->语句块->表达式 3。


while 循环:


while (表达式) {  //语句块}
复制代码


表达式为true,执行语句块,为false跳出循环。


do...while 循环:


do {
//语句块
} while (表达式)
复制代码


至少执行一次语句块,表达式为true执行语句块,为false退出循环。

2.8 数组

2.8.1 数组的基本操作

创建数组:


//1let arr1 = new Array();//2let arr2 = [];//3let arr3 = [1,2,3,4,5,6,7,8,9,0];//4let arr4 = [1,"sss","777",2.33,null,undefined];//5let arr5 = [12,[],[1,3,5,null,"sss"],false,true];
复制代码


由于 js 里面的类型为弱类型,基本上什么类型的值都能赋值,所以 js 的数组什么都可以放,可以理解为 java 的 Object 数组,但不完全相同。


输出数组:


//基本语法:console.log(数组名);
复制代码


就像下面这样:


console.log(arr1);console.log(arr2);console.log(arr3);console.log(arr4);console.log(arr5);
复制代码


运行结果:



逐个元素输出,首先使用 length 获取数组长度,然后访问每个元素输出就行。


let arr = [1,2,3,4,5,6,7,8,9,0];for (let  i = 0; i < arr.length; i++) {    console.log(arr[i]);}
复制代码


运行结果:


2.8.2 越界访问数组

js 的数组是可以越界访问的,得到的结果是 undefined。


let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr[100]);console.log(arr[-1]);
复制代码


运行结果:



除了越界访问,还可以越界修改数组的值,那么此时数组的长度就会发生改变。


let arr = [1,2,3,4,5,6,7,8,9,0];arr[100] = 22;console.log(arr);
复制代码


运行结果:



我们发现当越界将下标为100的值修改为22时,数组长度变成了101。中间填充的值均为undefined


但是你的下标为负整数时,数组的长度并不会发生改变,毕竟你的下标格式都不合法,但是会生成一个键值对添加到数组中,那么此时对于 js 中的数组,更像是对象,而数组和多出来的键值对可以理解为该对象里面的属性,同理当下标如果是字符串,浮点数等,也是相同的情况,既然是属性你也可以使用.去访问。


let arr = [1,2,3,4,5,6,7,8,9,0];arr[-1] = -1;arr["hello"] = 123;console.log(arr);
复制代码


运行结果:



其实长度也是数组的一个属性,你可以访问它也可以修改它。


let arr = [1,2,3,4,5,6,7,8,9,0];arr.length  = 100;console.log(arr);
复制代码


运行结果:



长度改小,会优先保留前面的数据,你再改回来,数据也不会回来的。


let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr);arr.length = 5;console.log(arr);arr.length = 10;console.log(arr);
复制代码


运行结果:


2.8.3 插入删除替换元素

可以使用 push 方法进行数组元素的追加,即在数组的最后面插入元素。


let arr = [];
for (let i = 0; i < 10; i++) { arr.push(i+1);}console.log(arr);
复制代码


运行结果:



我们可以使用splice方法来对数组进行,基本语法:


array.splice(index, howmany, item1, ....., itemX);
复制代码



let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr);//删除前arr.splice(2, 3);//表示从下标2进行删除,删除3个元素console.log(arr);
复制代码


运行结果:



它也可以实现元素的替换。


let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr);//替换前arr.splice(2, 3, 666, 777, 888);//表示从下标2进行替换,替换3个元素console.log(arr);
复制代码


运行结果:



运用巧妙一点,也能在某一位置插入元素。


let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr);//插入前arr.splice(2, 0, 666);//表示在2下标后插入一个66console.log(arr);
复制代码


运行结果:



当然由于 js 数组是可以越界的,所以也可以使用下标的方式在数组尾插元素。


let arr = [1,2,3,4,5,6,7,8,9,0];console.log(arr);//插入前arr[arr.length] = 66;console.log(arr);
复制代码


运行结果:



当然有关 js 这个数组对象的方法还有很多,具体参考:https://www.w3school.com.cn/jsref/jsref_obj_array.asp

2.9 函数

JavaScript 的函数还是挺有特点的相比于 java 的方法,它不用指定返回值类型,有就返回,没有就不返回,它需要使用function关键字来表示它的身份,即函数,它的形参列表不需要返回值,它是 JavaScript 家族的一等公民,与变量平起平坐。


函数的定义、函数声明、函数调用:


//函数的定义、函数声明function func(形参列表,不需要声明类型,毕竟js是弱类型的语言) {        //函数语句块        return 返回值;}//函数调用函数名(实参列表);//无返回值let varname  = 函数名(实参列表);//有返回值
复制代码


调用可以出现在定义之前:


hello();hello();function hello() {    console.log("hello");}hello();hello();
复制代码


运行结果:



由于 JavaScript 是弱类型语言,函数的变量类型可以随便放,所以也不需要重载,泛型。


function add(a, b) {    return a + b;}console.log(add(10,20));console.log(add("10","20"));console.log(add(1024,"hello"));console.log(add(true,false));console.log(add(undefined,20));console.log(add(undefined,"20"));
复制代码


运行结果:



其实吧,形参有那么多,你少传一点也可以,只不过没有收到传入参数值的变量默认值为undefined,此时进行数学运算值为NaN


function add(a,b,c,d,e,f,g) {    return a + b + c + d + e + f + d + g;}console.log(add(10, 20));console.log(add(10, 20, 30));console.log(add(10, 20, 30, 40));console.log(add(10, 20, 30, 40, 50));console.log(add(10, 20, 30, 40, 50, 60));console.log(add(10, 20, 30, 40, 50, 60, 70));
复制代码


运行结果:



加个判断,将未初始化的值,赋值为 0,就能进行计算了。


function add(a,b,c,d,e,f,g) {    // if(a === undefined) {    //     a = 0;    // }    // //相当于    // a = a || 0;    a = a || 0;    b = b || 0;    c = c || 0;    d = d || 0;    e = e || 0;    f = f || 0;    g = g || 0;    return a + b + c + d + e + f + d + g;}console.log(add(10, 20));console.log(add(10, 20, 30));console.log(add(10, 20, 30, 40));console.log(add(10, 20, 30, 40, 50));console.log(add(10, 20, 30, 40, 50, 60));console.log(add(10, 20, 30, 40, 50, 60, 70));
复制代码


运行结果:



参数多了,也没什么事,前面已经成功传入的参数,会正常进行运算。


function add(a,b,c,d,e,f,g) {    // if(a === undefined) {    //     a = 0;    // }    // //相当于    // a = a || 0;    a = a || 0;    b = b || 0;    c = c || 0;    d = d || 0;    e = e || 0;    f = f || 0;    g = g || 0;    return a + b + c + d + e + f + d + g;}console.log(add(10, 20, 30, 40, 50, 60, 70));console.log(add(10, 20, 30, 40, 50, 60, 70, 80, 90));//参数传多了,多传的参数接收不到
复制代码


运行结果:



函数就像普通变量一样,可以赋值给变量,然后该变量可以调用该函数,相当于 C 语言中的函数指针,所以 js 中的函数也被叫做“一等公民”。


function print(s) {    console.log(s);}let p = print;p("hello");//typeof获取类型console.log(typeof p);
复制代码


运行结果:



合二为一:


//合二为一的写法let p = function print(s) {    console.log(s);}p("hello");
复制代码


运行结果:



可以省略函数名,然后使用变量接收匿名函数。


//匿名函数赋值调用,常用let p = function (s) {    console.log(s);}p("hello");
复制代码


运行结果:



在 js 中,函数里面是可以定义函数的,而且可以无限的嵌套,这与 java 不同。


在 JavaScriptES6 之前,作用域只有全局作用域和函数作用域,并没有块级作用域,而在 ES6 之后引入了 let,也有了块级作用域,定义的在大括号内部的变量在大括号外面是无法访问的。因为 js 中的函数可以嵌套定义,对于里层函数的变量,如果在函数本体找不到就会一级一级向上查找。


let num = 10;function func1() {    function func2 () {        function func3 (){            console.log(num);        }        func3();    }    func2();}func1();
复制代码


运行结果:



let num = 10;function func1() {    let num = 20;    function func2 () {        let num = 30;        function func3 (){            console.log(num);        }        func3();    }    func2();}func1();
复制代码


运行结果:


2.10 对象

js 的对象里面的是属性是通过键值对的方式来创建的。


方式一:直接为对象添加属性来进行创建。


let 变量名 = {  //属性  键:值,  ...,  //函数  键:function (){    //函数语句块  },  ...,  //最后一个属性逗号可以省略}
复制代码


栗子:


let animal = {    name: "小鸭子",    age: 18,        running: function (){        console.log(this.name + "会奔跑");    },    swimming:function () {        console.log(this.name + "会游泳")    }}console.log(animal.name);console.log(animal.age);animal.swimming();animal.running();
复制代码


运行结果:



方式二:new Object(),然后添加属性,不推荐!


let animal = new Object();animal.name = "小鸭子";animal.age = 18;animal.running = function (){    console.log(animal.name + "会奔跑");}animal.swimming = function (){    console.log(animal.name + "会游泳");}console.log(animal.name);console.log(animal.age);animal.swimming();animal.running();
复制代码


运行结果:



方式三:使用 this,并使用类似与 java 构造方法的方式创建对象。


function 构造函数名(形参列表) {  this.属性 = 值;  this.函数 = function...;}//创建let obj = new 构造方法名(实参);
复制代码


栗子:


function animal() {    this.animal;    this.age;    this.swimming = function () {        console.log(this.name + "会游泳");    }    this.running = function() {        console.log(this.name + "会奔跑");    }}
let ani = new animal();ani.name = "小鸭子";ani.age = 18;console.log(ani.name);console.log(ani.age);ani.swimming();ani.running();
复制代码


运行结果:





下期预告: JavaScript DOM API

发布于: 刚刚阅读数: 3
用户头像

未见花闻

关注

还未添加个人签名 2021.11.15 加入

还未添加个人简介

评论

发布
暂无评论
JavaScript基础语法知识遨游记_6月月更_未见花闻_InfoQ写作社区