admin 管理员组

文章数量: 1087652

Java Script基础语法

目录

  • 引言
  • 一、JavaScript 的书写形式
    • 1.1行内式
    • 1.2 内嵌式
    • 1.3 外部式
  • 二、输入输出
    • 2.1 输入: prompt
    • 2.2 输出: alert
    • 2.3 输出: console.log
  • 三、语法概览
    • 3.1 变量的使用
    • 3.2 基本数据类型
  • 四、运算符
    • 4.1相等运算符
    • 4.2 逻辑运算符
  • 五、数组
    • 5.1 创建数组
    • 5.2 获取数组元素
    • 5.3 获取数组长度
    • 5.4 使用 push 进行追加元素
    • 5.5 删除数组中的元素.
  • 六、函数
    • 6.1 语法格式
    • 6.2 函数表达式
    • 6.3 关于参数个数
    • 6.4 作用域
  • 七、对象
    • 7.1 使用 字面量 创建对象 [常用]
    • 7.2 使用 new Object 创建对象
    • 7.3 使用构造函数创建对象
    • JavaScript 的对象和 Java 的对象的区别

引言

JavaScript (简称 JS)

  • 是世界上最流行的编程语言之一;
  • 是一个脚本语言, 通过解释器运行;
  • 主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行;
    Node.js这是一个js 的运行平台.(对标的是浏览器)浏览器是运行在客户的.Node.js 既可以运行在客户端,也可以运行在服务器上(单独的执行程序).就可以给js赋予客户端开发/服务器开发的能力.

JavaScript 的能做的事情:

  • 网页开发(更复杂的特效和用户交互)
  • 网页游戏开发
  • 服务器开发(node.js)
  • 桌面程序开发(Electron, VSCode 就是这么来的)
  • 手机 app 开发

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

JavaScript 和 HTML 和 CSS 之间的关系:

  • HTML: 网页的结构(骨)
  • CSS: 网页的表现(皮)
  • JavaScript: 网页的行为(魂)

JavaScript 运行过程:

  • 编写的代码是保存在文件中的, 也就是存储在硬盘(外存上).
  • 双击 .html 文件浏览器(应用程序)就会读取文件, 把文件内容加载到内存中(数据流向: 硬盘 => 内存)
  • 浏览器会解析用户编写的代码, 把代码翻译成二进制的, 能让计算机识别的指令(解释器的工作)
  • 得到的二进制指令会被 CPU 加载并执行(数据流向: 内存 => CPU)

    浏览器分成渲染引擎 + JS 引擎.
    渲染引擎: 解析 html + CSS, 俗称 “内核”;
    JS 引擎: 也就是 JS 解释器. 典型的就是 Chrome 中内置的 V8;

JS 引擎逐行读取 JS 代码内容, 然后解析成二进制指令, 再执行

JavaScript 的组成:
ECMAScript(简称 ES): JavaScript 语法;
DOM: 页面文档对象模型, 对页面中的元素进行操作;浏览器提供的一组,操作页面元素的API;
BOM: 浏览器对象模型, 对浏览器窗口进行操作;浏览器提供的一组,操作浏览器窗口的API;

但是要想完成更复杂的任务, 完成和浏览器以及页面的交互, 那么就需要 DOM API 和 BOM API.这主要指在浏览器端运行的 JS. 如果是运行在服务端的 JS , 则需要使用 node.js 的 API,就不太需要关注 DOM 和 BOM.

一、JavaScript 的书写形式

JavaScript 代码可以嵌入到 HTMLscript 标签中.

1.1行内式

直接嵌入到 html 元素内部:

<input type="button" value="点我一下" οnclick="alert('haha')">

注意, JS 中字符串常量可以使用单引号表示, 也可以 使用双引号表示.
HTML 中推荐使用双引号, JS 中推荐使用单引号

1.2 内嵌式

写到 script 标签中:

<script>alert("haha");
</script>

1.3 外部式

写到单独的 .js 文件中:

然后到另一个文件中对其进行引用:

<script src="app.js">

关于注释

  • JS的注释//
  • HTML的注释:<!-- -->
  • CSS的注释:/* */

二、输入输出

2.1 输入: prompt

弹出一个输入框:

 prompt("请输入名字:");

2.2 输出: alert

弹出一个警示对话框, 输出结果:

alert("hello");

2.3 输出: console.log

在控制台打印一个日志(供程序员看):

// 向控制台输出日志
console.log("这是一条日志");

三、语法概览

3.1 变量的使用

定义一个变量:

var变量名=初始值;
		 // 创建变量let num = 10;//创建一个名为num的,数字类型的变量var s = 'hello';//创建了一个名字为s的,字符串类型的变量.var arr = [];//创建了一个名字为arr的,数组类型的变量.

现在更倾向于使用let来代替var .var是旧版本(早期的设计),有很多地方其实是违背直觉.

使用变量:读取+修改:

在变量的修改的时候,有个小问题:如果本来num是一个数字类型,在赋值的时候可以给它赋一个数字类型,也可以赋一个字符串类型,也可以赋任意类型,这个时候num变量的类型,也就随之发生改变了。

 		num = 20;//变量的类型可以在运行的过程中随着赋值的改变而发生改变---‘动态类型’num = 'hello';console.log(num)

变量的类型可以在运行的过程中随着赋值的改变而发生改变,称为“动态类型”。(Python,PHP,Ruby…)
像Java这样的语言,不支持这种运行时类型发生改变.这种行为,称为"静态类型"。(C,C++,Java,Go,Rust…)

3.2 基本数据类型

JS 中内置的几种类型:

  1. number: 数字. 不区分整数和小数.
var a = 07; // 八进制整数, 以 0 开头
var b = 0xa; // 十六进制整数, 以 0x 开头
var c = 0b10; // 二进制整数, 以 0b 开头

一个进制数字对应三个二进制数字,一个十六进制数字对应个二进制数字. (两个十六进制数字就是一个字节).

特殊的数字值:

  • Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.
  • -Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.
  • NaN: 表示当前的结果不是一个数字.
var max = Number.MAX_VALUE;
// 得到 Infinity
console.log(max * 2);
// 得到 -Infinity
console.log(-max * 2);
// 得到 NaN
console.log('hehe' - 10);
//和Java类似,如果把字符串和数字相加,那么就会得到一个“字符串拼接”的效果.
console.log('hehe' - 10);//hehe10

可以使用 isNaN 函数判定是不是一个非数字:

console.log(isNaN(10)); // false
console.log(isNaN('hehe' - 10)); // true
  1. boolean: true 真, false 假.

Boolean 参与运算时当做 10 来看待:

console.log(true + 1);//2
console.log(false + 1)//1

这样的操作其实是不科学的. 实际开发中不应该这么写.

  1. string: 字符串类型.

如果字符串里本身就包含了引号,这个时候就可以通过单双引号灵活搭配的形式,来避免使用转义字符:

		let s1 = "my name is 'zhang'";console.log(s1);let s2 = 'my "name" is zhang ';console.log(s2);let s3 = "My name is \"zhangsan\"";console.log(s3);


有些字符不方便直接输入, 于是要通过一些特殊方式来表示:

\n
\\
\'
\"
\t

求长度:求长度通过length属性

  		let s = '哈哈';console.log(s.length);//2

此处这里的长度,单位是“字符"。

字符串拼接(和Java类似)直接使用来进行拼接。
数字和字符串拼接得到字符串;数字和数字拼接得到的是数字。

		//字符串拼接let a = 'hello';let b = 20;console.log(a+b);//hello20
  1. undefined: 只有唯一的值 undefined. 表示未定义的值.

如果一个变量没有被初始化过, 结果就是 undefined, 是 undefined 类型:

		 let c;console.log(c);//undefined

undefined 和字符串进行相加, 结果进行字符串拼接:

let a;
console.log(a + "10"); // undefined10

undefined 和数字进行相加, 结果为 NaN:

let a;
console.log(a + "10); // NaN
  1. null: 只有唯一的值 null. 表示空值.
 		let d = null;console.log(d);//nullconsole.log(d + 10); // 10console.log(d + "10"); // null10

null 和 undefined 都表示取值非法的情况, 但是侧重点不同.
null 表示当前的值为空. (相当于有一个空的盒子)
undefined 表示当前的变量未定义. (相当于连盒子都没有)

如果一个编程语言,越支持隐式类型转换,认为类型越弱.(C,JS,PHP认为是弱类型的编程语言);
如果一个编程语言,越不支持隐式类型转换,认为类型越强.(Java, Go, Python认为是强类型的编程语言);
强类型,意味着类型之间的差异更大,界限是更明确的;
弱类型,意味着类型之间的差异不大,界限是更模糊的;

静态类型/动态类型vs强类型/弱类型是不相关的概念(正交)

C++是兼容C的.(意味着C的隐式类型转换,对于C++也是同样支持的)

四、运算符

JavaScript 中的运算符和 Java 用法基本相同. 此处不做详细介绍。
这里介绍下比较运算符里面的相等运算符

4.1相等运算符

JS中比较相等,有两种风格:

  1. == 比较相等(会进行隐式类型转换)
    !=
    只是比较两个变量的值,而不比较两个变量的类型.如果两个变量能够**通过隐式类型转换,转成相同的值,**此时就认为这两个变量是相等的。

  2. === 比较相等(不会进行隐式类型转换)
    !==
    既要比较变量的值,也要比较类型.如果类型不相同,就直接认为不相等.

 		let e = 10;let f = '10';console.log(e == f);//trueconsole.log(e === f);//false

谈到比较两个对象,有三个维度的比较:
1.比较身份.(是不是同一个对象)
2.比较值.(对象里存储的数据是否相同)
3.比较类型.(两个对象是否是同一个类型)

Java中 ==比较身份.equals可以被重写.不重写默认也是比较身份.通过重写来设定成比较值.instanceof 比较类型.
JS: ==只是比较值.,===同时比较值和类型.

4.2 逻辑运算符

&&、||这俩个运算符和Java 中的&&和||差别挺大的。
Java中的&&和||行为非常简单.就是返回一个true或者falseJS中的&&和||返回的是其中的一个表达式

c = a || b
如果a的值,为真(非0),此时c的值,就是表达式a的值.
如果a的值,为假(为0),此时c的值,就是表达式b的值.
c = a && b也是类似:
如果a的值为假, 此时c的值,就是表达式a的值.
如果a的值为真, 此时c的值,就是表达式b的值.

这属于一种短路求值:如果a这边已经能确定表达式的值了,就不必计算b了。

	let x = null;if(!x){x= 0;}// 等价于x = x || 0;

JS中,不区分整数和小数,都是number.

  console.log(1/2);//0.5

五、数组

5.1 创建数组

  1. 使用 new 关键字创建
let arr = new Array();

这种写法,更像是, Java 中创建了一个对象(很少使用)

  1. 使用字面量方式创建 [常用]
 		let arr1 = [];let arr2 = [1,2,3,4];let arr3 = [1,'hello',undefined,true];//数组中保存的内容称为 "元素"console.log(arr1);console.log(arr2);console.log(arr3);


JS 的数组不要求元素是相同类型.

5.2 获取数组元素

使用下标的方式访问数组元素(从 0 开始):

 		let arr3 = [1,'hello',undefined,true];//获取数组中的元素console.log(arr3[0]);console.log(arr3[1]);console.log(arr3[2]);console.log(arr3[3]);


如果下标超出范围读取元素, 则结果为 undefined:

		let arr3 = [1,'hello',undefined,true];console.log(arr3[8]);//undefined      

当给超出数组下标的元素赋值时,长度变成了101,然后数组的内容,前四个元素不变,下标为100的元素是10.但是中间的空属性*96意思就是中间这些元素仍然是undefined

		let arr3 = [1,'hello',undefined,true];arr3[100] = 10;console.log(arr3);


如果给数组下标为-1的元素赋值:

 	//-1是一个属性,并没有影响到数组的长度arr3[-1] = 10;console.log(arr3);


JS 中的数组,不是一个正经数组!除了能接数组的活,还能接map的活(表示键值对)=>这里说数组是一个map,更准确的说是一个“对象”.
在JS里,是可以在运行时给对象新增属性的.
下面的arr['hello']就是在给arr这个对象新增了一个属性.属性的名字是hello,属性的值是10.

 	 	arr.hello = 10;arr['hello'] = 10;console.log(arr);//[hello: 10]console.log(arr['hello']);//10console.log(arr.hello);//10

这些语法都不是JS独有的.动态类型的语言都是这样设定的。(PHP的设定方式几乎和JS一模一样,但是 Python 略有差别,本质不变)

5.3 获取数组长度

通过.length就能获取到。JS 里,length属性是可以改的。

 		let arr2 = [1,2,3,4];console.log(arr2.length);

5.4 使用 push 进行追加元素

最常见的插入操作, push方法能够给数组末尾追加一个元素.(Java ArrayList里面的add操作)。
代码示例: 给定一个数组, 把数组中的奇数放到一个 newArr 中:

var arr = [9, 5, 2, 7, 3, 6, 8];
var newArr = [];
for (var i = 0; i < arr.length; i++) {if (arr[i] % 2 != 0) {newArr.push(arr[i]);}
}console.log(newArr);
		 let arr4 = [];for(let i = 0;i < 10;i++){arr4.push(i);}console.log(arr4);

5.5 删除数组中的元素.

splice这个方法,针对数组中的某个区间进行替换.既可以用于删除,也可以用于插入元素.

		 //删除元素arr4.splice(3,2);//从下标为3的位置开始,删除两个元素console.log(arr4);

六、函数

函数(function)和方法(method)是同一个东西,不同的马甲。
通常情况下,不去考量这两个概念的区别.但是如果非要考量,可以这样理解:
函数是和“对象"独立开来的代码片段.
方法是依托于对象的代码片段. 方法=>成员函数
在Java中,由于本身这样的代码片段都是依托于类和对象的.因此Java中就都是“方法"。

6.1 语法格式

// 创建函数/函数声明/函数定义
function 函数名(形参列表) {函数体return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值

这里的形参列表,不必写参数类型,返回值类型也不需要写。

函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.

function f() {console.log("hello");
}
f();//hello

调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.
函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)

6.2 函数表达式

另外一种函数的定义方式。

	    // function hello() {//     console.log("hello");// }//hello是一个函数名.hello后面没有(),//说明这个操作,不是函数调用而只是一个单纯的函数的赋值.//f1是function类型的变量// let f1= hello;//通过f也能够调用到上面的 hello 函数//f1();//hello//上面可以合并为,也可以省略hello//匿名函数--》lambda表达式let f1= function () {console.log("hello");};console.log(typeof (f1));//functionf1();//hello

此时形如 function() { } 这样的写法定义了一个匿名函数, 然后将这个匿名函数用一个变量来表示.后面就可以通过这个 f1 变量来调用函数了.

6.3 关于参数个数

实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配.

  1. 如果实参个数比形参个数多, 则多出的参数不参与函数运算;
  2. 如果实参个数比形参个数少, 则此时多出来的形参值为 undefined;
//最多可以支持7个参数相加
function add(a,b,c,d,e,f,g) {//第一种写法// if(a == undefined){//     a = 0;// }//另外一种写法//如果不对下面的值进行处理,则返回的结果是NaNa = 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+g;}console.log(add(10,20));//30console.log(add(10,20,30));//60

传入的实参类型是可以任意的.只要能够支持函数内部的逻辑(比如此处要求两个参数能进行相加即可):

 	function add(x,y){return x + y;}let result = add(1,2);console.log(result);result =  add("hello","world");console.log(result);result = add(10,"hello");console.log(result);

正因为有这样的特性,JS天然就是不需要"泛型"/"重载"这样的语法的.

6.4 作用域

作用域:某个标识符名字在代码中的有效范围.

ES6其实是JS的版本.JS原名ECMAScript,也可以简称为ES. JS的版本都是用ES数字来表示的.JS中的最新版本也是到ES十几,ES6的地位就相当于Java8在java 中的地位.

ES6 标准之前, 作用域主要分成两个:
全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
局部作用域/函数作用域: 在函数内部生效.
ES6之后,引入了let,也就有了块级作用域.一个变量{}内部定义,是无法被{}外部访问的。在JS里面,{}内部的代码,是可以访问到{}外部的变量的。

作用域链:内部函数可以访问外部函数的变量. 采取的是链式查找的方式. 从内到外依次进行查找。

 		let num = 10;function f3() {function f2() {console.log(num);}f2();}f3();

JS中的作用域,是支持"逐级向上"查找的.当前是在f2这个函数里尝试打印num.但是在f2中,没有num变量,于是就往上级找,找到了f3这里,但是在f3里,也没num.
于是继续往上找,找到了全局作用域.找到了num(如果最后的全局作用域也没找到,就会报错).

如果在作用域链的不同节点上,存在多个同名的变量咋办?
从里往外找,先找到谁就算谁

七、对象

对象就是一些属性和方法的集合.在 JS 中, 字符串, 数值, 数组, 函数都是对象.
在Java中,对象需要先有类,然后针对类的实例化才产生对象.Java中,类可以视为是一种自定义的类型.(Cat类和Dog类两个不同的类型).
在JS 中,对象是不依托于类的,在JS中所有的对象都是一个类型. object
在JS中,直接通过{}的方式,就可以创建对象.

7.1 使用 字面量 创建对象 [常用]

使用 { } 创建对象

 //对象let student={name: '张',age:20,height:180,weight: 120,sing:function () {console.log("ni");},jump:function () {console.log("舞蹈");}};console.log(student.name);//zhangconsole.log(student.age);//20student.sing();//ni

每个属性和方法,其实都是通过"键值对"这样的方式来表达的.{}表示这是个对象.
键值对之间使用,来分割,键和值之间使用:来分割.后续就可以根据student.属性名方式来进行访问了.对象的定义(和Java有一定区别)

7.2 使用 new Object 创建对象

var student = new Object(); // 和创建数组类似student.name = "蔡徐坤";student.height = 175;student['weight'] = 170;student.sayHello = function () {console.log("hello");
}console.log(student.name);console.log(student['weight']);student.sayHello();

JS中一个对象中有哪些成员,也都是动态可以改变的,注意, 使用 { } 创建的对象也可以随时使用 student.name = "蔡徐坤"; 这样的方式来新增属性.

7.3 使用构造函数创建对象

前面的创建对象方式只能创建一个对象. 而使用构造函数可以很方便的创建多个对象.

基本语法

function 构造函数名(形参) {this.属性 = 值;this.方法 = function...
}
var obj = new 构造函数名(实参);
  • 当看到函数内部,通过this.这样的方式来创建属性的时候,此时这个函数大概率就是构造函数了.
  • 构造函数的函数名首字母一般是大写的.
  • 构造函数的函数名可以是名词.
  • 构造函数不需要 return.
  • 创建对象的时候必须使用 new 关键字.

不使用构造函数创建对象:

var mimi = {name: "咪咪",type: "中华田园喵",miao: function () {console.log("喵");}
};
var xiaohei = {name: "小黑",type: "波斯喵",miao: function () {console.log("猫呜");}
}
var ciqiu = {name: "刺球",type: "金渐层",miao: function () {console.log("咕噜噜");}
}

使用构造函数重新创建Cat对象:

function Cat(name, type, sound) {this.name = name;this.type = type;this.miao = function () {console.log(sound); // 别忘了作用域的链式访问规则}
}var mimi = new Cat('咪咪', '中华田园喵', '喵');var xiaohei = new Cat('小黑', '波斯喵', '猫呜');var ciqiu = new Cat('刺球', '金渐层', '咕噜噜');console.log(mimi);mimi.miao();

实际上JS在穿件对象的时候,以第一种写法为主。

JavaScript 的对象和 Java 的对象的区别

  1. JavaScript 没有 “类” 的概念
    JS没有class这个概念,适用于ES6之前.ES6之后,也引入了class 关键字,可以让定义对象,就更接近于Java 了这种方式,仍然没有上述第一种方法简单.
    因此,在JS中也是有一些现成的对象的,像数组,本质上也可以视为是一个对象。
  2. JS里没有封装,继承,多态这样的一些面向对象的典型特性
    JS中没有原生提供继承这种机制的.但是JS里有一个曲线救国的方法,“原型”,基于原型机制,可以模拟实现一个类似于继承的效果.(把一个对象的所有属性,给自动的加入到一个新的对象中)
  3. JavaScript 对象不区分 “属性” 和 “方法”
    JavaScript 中的函数是 “一等公民”, 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行。
  4. JavaScript 对象没有 private / public 等访问控制机制.
    对象中的属性都可以被外界随意访问.

本文标签: Java Script基础语法