直接写到 script 标签里
写到单独的文件中
使用了 src 属性的 script 标签了之后,标签内部不能再写 JS 代码了,写了也不会生效。
在标签里面,通过一些属性来实现。(把 JS 代码,嵌入到标签里)
onclick 是 div 标签的属性(绝大部分的 HTML 标签都有这个属性),属性的值就是一段 JS 代码,这段 JS 是使用
""
引起来的,因此 JS 里面如果使用到 字符串,建议使用'
,非要使用双引号则需要\"
。onclick 的意思 " 点击的时候,发生个什么事情 "。用户啥时候点,就啥时候执行,用户点几次,就执行几次。
单行注释 // [建议使用]
多行注释 /* */
弹出一个输入框
prompt(“请输入您的姓名:”);
弹出一个警示对话框, 输出结果
alert(“hello”);
不太好用,由于 alert 弹出的是 " 模拟对话框 " (如果用户不点掉对话框,无法操作界面其他内容)
在控制台打印一个日志(供程序员看)
console.log(“这是一条日志”);
这个输出是输出到控制台,是程序员调试 JS 代码的重要手段
var name = ‘zhangsan’;
var age = 20;
此处没有写 int/String 类型名,而是直接写了 var,var 单纯的表示,这是一个变量,变量的类型如何决定呢?则是看变量的初始化是啥类型的。
相较于 C++ 和 Java 而言,JS 有一个很大的差别,同一个变量,是可以改变类型的。
动态类型:一个变量在运行的过程中,类型可以发生改变。(JS,Python,PHP…)
静态类型:不能发生改变(编译报错)(C,C++,Java)
注意:很多人把 Java 和 JS 之间的语法差异归结为 " 弱类型 " 其实是错的,其实语法差异大部分是由 " 动态类型 " 带来的,反而弱类型强类型这个区别语法并不大。
- 如果变量 n 当前保存的是一个整数,n 的内存相当于是保存了 64 位的整数
- 如果变量 n 当前保存的是一个小数,n 的内存相当于保存了 双精度 浮点数,也遵守 IEEE 754 标准的。
JS 里的 string 和 Java 里的字符串很相似,例如 Java 中支持字符串 + 相加操作符就表示 " 拼接 ",JS 里的字符串也能拼接。
也是和 Java 中的类似的, true 和 false。
如上类型也是允许的,相当于是把 Boolean 类型隐式转换成了一个数字。(如果一个编程语言,不太支持隐式类型转换,强类型,反之。类型强弱,描述的是类型之间的界限是不是非常严格,界限越严,类型越强)
如果某个东西没有被定义,直接去访问,一般不会报错,而是得到一个 undefined
由于 JS 是弱类型,如果拿一个 undefined 和其他类型进行混合运算,不会报错,而是把 undefined 转成了 string。
注意加单引号,不然计算的结果就是 NaN(not a number)
这个类型里只有一个值 null
类似于 Java 中的空引用,使用 null 表示无效值
undefined 表示的是未定义 " 非法的值 ";null 表示的是 " 无效 ",合法的值。
在官方显示是 object 类型,但是这是个 bug,为了考虑到兼容性,所以没有改动,实则是 null 类型。
JS 中的重要的部分,类似于 Java 中的对象了。Java 中的对象,每个对象都是各自的类型(每个类都代表不同的类型),JS 中没有 类 这样的概念,所有的对象都是 object 类型。
JavaScript 中的运算符和 Java 用法基本相同,此处不做详细介绍了。
+
-
*
/
%
=
+=
-=
*=
/=
%=
++
自增1--
自减1<
>
<=
>=
==
比较相等(会进行隐式类型转换)!=
===
比较相等(不会进行隐式类型转换)!==
在 JS 中,比较字符串内容,也是使用 = =,绝大部分编程语言,比较字符串内容,都是使用 = =,只有 C(strcmp)和 Java(equals)例外。
用于计算多个 boolean 表达式的值
&&
与: 一假则假||
或: 一真则真!
非&
按位与|
按位或~
按位取反^
按位异或<<
左移>>
有符号右移(算术右移)>>>
无符号右移(逻辑右移)基本语法格式:条件表达式为 true,则执行 if 的 { } 中的代码。
// 形式1
if (条件) {
语句
}
// 形式2
if (条件) {
语句1
} else {
语句2
}
// 形式3
if (条件1) {
语句1
} else if (条件2) {
语句2
} else if … {
语句…
} else {
语句N
}
条件 ? 表达式1 : 表达式2
条件为真, 返回表达式1 的值. 条件为假, 返回表达式2 的值
switch (表达式) {
case 值1:
语句1;
break;
case 值2:
语句2:
break;
default:
语句N;
}
while (条件) {
循环体;
}
执行过程:
结束这次循环
结束整个循环
for (表达式1; 表达式2; 表达式3) {
循环体
}
执行过程:
使用 new 关键字创建
let arr = new Array();
使用字面量方式创建 [常用]
let arr2 = [];
let arr3 = [1,2,3,4];
let arr4 = [1,‘hello’,true,null];
注意:JS 的数组不要求元素是相同类型
使用下标的方式访问数组元素(从 0 开始)
当 JS 中的下标越界了,不会报错!而是返回 undefined 。
修改数据会给对应下标放上元素
如果下标是负数会怎样?
如果下标是字符串会怎样呢?
可以看到键值对也出现在结果里了,此时此刻这个数组已经不仅仅是一个数组了,更是一个 map。
数组里存储的数据就是两个部分了:
-1 这个下标的内容存在于第二个部分
2.往中间新增,本质上是进行替换了,把数组中的部分元素替换成别的元素了
从下标为 2 的元素开始删除,删除几个元素
后面的参数不写就是直接删除,写了多个就是 删除/替换 多个。
如果第二个参数写作 0 ,那么就不是删除 / 替换元素了,而是插入元素
函数定义:
function 函数名(形参列表) {
函数体
return 返回值;
}
- function --> 关键字
- 函数名 --> 当前函数名字
- 形参列表 --> 写几个形参
注意:没有看到 “返回值类型” ,所以返回啥都行。(在 Java 中里面的方法,只能返回一种类型的数据。JS 则不要求,一个函数的返回类型可以不相同,包括参数形参,每个参数是啥类型也可以随意指定)
例如在一个函数中,形参不必写类型,啥类型都行,只要保证传入的类型可以正常执行即可
函数调用
JS 中的函数,只要传入的实参,能够满足函数体中的运算要求,就是可以的。
别的语言中,一般是要求,函数的形参个数要和实参个数匹配,JS则不要求,实参是多还是少,都无所谓,如果实参多了,多出来的实参,就忽略了;如果实参少了,多出来的形参,就是undefined,也不会报错。
写一个函数 能够支持 N 个值的相加
由于上述代码看起来不简洁,于是想到在 JS 中 || 的返回值不是 true 或者 false,而是a || b的时候,如果 a 是true,整个表达式返回a的值,如果 a 是 false,则整个表达式返回 b 的值。
万一参数超过了 6 个,想要任意参数咋办?
类似于 splice 能支持任意个参数一样,咱们自己写的函数也是可以的
JS 函数的内部,有一个内置的变量,叫做arguments,相当于一个数组,这个数组里就放了所有的实参。
创建了变量,名字叫做add。对add进行初始化,拿着一个函数进行初始化。add这个变量的类型,就是函数类型。
上述操作很多语言都支持,但是 Java 不支持,有人说 Java 是一个纯粹的面向对象的编程语言,但是 Java 中很多东西不是对象,比如一个方法,import 的包,都不是对象。(判定是不是对象很好判定:能不能取属性,能不能调用方法,能不能获取到对象的身份)
但是在JS里,函数也是一个对象,就和普通的对象没啥区别,可以把函数保存到一个变量中,也可以把函数作为另一个函数的参数,还可以把函数作为另一个函数的返回值,这个设定称为 “函数是一等公民” 。
使用 let 定义的变量是 “块级作用域” ,在当前 {} 里生效的。
在使用某个变量的时候,就会先在当前{}去找,如果找不到,就往外层 {} 去找。一直找到最顶层还找不到,就认为变量未定义。
从代码块里面一级一级往外找变量的这个过程,称为 “作用域链”
对象里面的数据,就非常类似于 "键值对” 结构,每个键值对都是使用,
来分割。
键和值使用:来分割。值也可以是函数。
还可以在运行的时候增加属性
同样是通过this表示当前对象的实例,进一步的就可以获取到对象中的属性和方法了
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();
注意, 使用 { } 创建的对象也可以随时使用 student.name = “蔡徐坤”; 这样的方式来新增属性.
var mimi = {
name: "咪咪",
type: "中华田园喵",
miao: function () {
console.log("喵");
}
};
var xiaohei = {
name: "小黑",
type: "波斯喵",
miao: function () {
console.log("猫呜");
}
}
此时写起来就比较麻烦. 使用构造函数可以把相同的属性和方法的创建提取出来, 简化开发过程
基本语法:
function 构造函数名(形参) {
this.属性 = 值;
this.方法 = function...
}
var obj = new 构造函数名(实参);
注意:
使用构造函数重新创建猫咪对象:
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();
对象其实就是 “属性” + “方法” .
类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 “月饼模子”
在 JavaScript 中的 “构造函数” 也能起到类似的效果.
而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象
在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了.
JavaScript 中的函数是 “一等公民”, 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.
对象中的属性都可以被外界随意访问.
继承本质就是 “让两个对象建立关联”. 或者说是让一个对象能够重用另一个对象的属性/方法.
JavaScript 中使用 “原型” 机制实现类似的效果.
多态的本质在于 “程序猿不必关注具体的类型, 就能使用其中的某个方法”.
C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方法的方式 来实现多态的效果.
但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的类型做出明确区分. 因此并不需要在语法层面上支持多态.