01--JS01--入门
JavaScript01: 基础入门
JavaScript 是一门能够运行在浏览器上的脚本语言,简称JS。
首先,Javascript这个名字的由来就很有意思,不少人认为 Javascript 和 Java 貌似很像,容易想象成Java的脚本
但其实两者之间没有任何关系,纯粹是商业碰瓷。
既然JS是可以运行在浏览器上的脚本,并且本质上,浏览器是执行HTML程序的
那么如何在HTML中引入JS呢?
方案一:直接在 <script>
标签中引入编写js代码
方案二:将js代码写在js文件中,然后通过<script>
标签的src属性,进行引入
两种方式运行出的效果是一致的
但注意:HTML程序在执行的时候是从上到下进行渲染的
那如果把脚本放在下面,和放在上面,是有一些不同的
一、基本数据类型
JS虽然是一个脚本语言,麻雀虽小,五脏俱全。
在js中也可以像其他编程语言一样,声明变量、条件判断、流程控制等.
1.1 主要数据类型
number // 数字 不论是整数还是小数, 数据类型都是number
string // 字符串
boolean // 布尔值 true和false 注意 全小写
object // 对象 这个比较特殊. 可理解为所有被new出来的东西,都是对象
undefined // 表示未定义 所有没有被定义过的东西,默认都是该类型 类似像空一样的东西
// null 与 undefined
null 空对象
undefined 空变量 声明了变量,但没有赋值
两者都可以表示空,本质都一样的. 都啥也干不了
两者都可以当做false,来看待就好了
// 查看变量类型
typeof 变量
var a = '猪总';
console.log(typeof n)
1.2 变量声明、注释
- 声明变量用
var
来声明 //
来表示单行注释,使用/* 内容*/
表示多行注释- 每行以
;
作为结束标志
// js启动严格模式 在scrip标签 最上方
"use strict"
var 变量名; // 创建一个变量, 此时该变量只能被赋值 es5
let 变量名; // es6新版 主要作用是变量作用域
const 常量 = 值; // 声明常量
var 变量名 = 值; // 创建一个变量, 并且有值
var 变量名 = 值1, 变量名2 = 值2, 变量名3 = 值3.....; // 一次创建多个变量,并都有值
var 变量名1, 变量名2, 变量名3 = 值3; // 一次创建多个变量, 并且只有变量3有值
1.3 运算符
JS中的运算符和Python几乎一致,但有些特殊的
// 1 连接运算符 与 或 非 and or not <==> && || !
var a = 10, b = 20, c = 30 ;
console.log(a > b && b > c); // false
console.log(!(a > b)) // true 注意括号
// 2 等于 == 和 ===
== 只判断 值是否一致
=== 会判断 数据类型和值 是否都一致
var a = "123";
var b = 123;
console.log(a == b); // true
console.log(a === b); // false
1.4 数据类型转换
// 1 string -> number : parseInt(字符串) 转化为整数
var a = "10086";
a = parseInt(a); // 字符串转成整数
console.log(a + 10); // 10096
// 2 number -> string : 数字.toString() 或者 数字 + ""
var a = 100;
var b = a.toString();
var c = a + "";
console.log(b);
console.log(c);
// 3 number -> string : 数字.toString(n进制) 数字转化成n进制的字符串
var m = 122;
var n = m.toString(16); // 数字转化成16进制的字符串
console.log(n); // 7a
// 4 进制转换
var a = 10;
// 16进制的数字是多少
var x = a.toString(16); // a
// AB的十进制是多少
var d = parseInt("AB", 16); // 171
1.5 关于自增 ++
// 1 在python中是没有++操作的,但是在js中是有的
a++; // a = a + 1
++a; // a = a + 1
a--; // a = a - 1 同理
--a; // a = a - 1
// 2 a++ 和 ++a的区别 困扰无数初学者的疑惑
1. 不论是a++还是++a. 目的都是让a自增1.
2. a++ 该表达式 整体的 运算结果是 a
++a 该表达式 整体的 运算结果是 a + 1
// 个人理解:
a 在 +前面,表示该表达式 是a 先赋值给表达式,a再自增
+ 在 a前面,表示该表达式 是a+1 先自增,再赋值给表达式
// 理解一下, 这里还好理解
var a = 10;
var b = a++;
console.log(b); // 10
console.log(a); // 11
var a = 10;
var b = ++a;
console.log(b); // 11
console.log(a); // 11
// 难度升级
var a = 10;
var a = a++;
console.log(a); // 10
var a = 10;
var a = ++a;
console.log(a); // 11
1.6 字符串操作
s.split('a') // 以a,进行字符串切割 返回的是 数组 attr[]
s.split() // 不指定字符,字符串切割 返回是 数组 [s] 以字符串本身为元素的数组
s.split('') // 以'' 为指定字符,字符串切割 返回是 数组 [s] 以字符串全部拆开为元素的数组
// eg:var s = 'edmond'
s.split('e') // ['e', 'dmond]
s.split() // ['edmond']
s.split('') // ['e', 'd', 'm', 'o', 'n', 'd']
s.substr(start_index, len) // 按照索引 + 长度,取子字符串 从start开始切, 切len个字符 注意是字符数,不是字节
s.substring(start, end) // 按照两个索引位置,取子字符串 从start切割到end
s.substr(start_index) // 只有一个参数时,两个都是从索引开始,截止到末尾
s.substring(start)
s.length // 字符串长度
s.charAt(i) // 第i索引位置的字符 s[i]
s.indexOf('xxx') // 返回xxx的第一次出现的索引位置, 如果没有xxx. 则返回-1 从左往右
s.lastIndexOf("xxx") // 返回xxx的最后一次出现的索引位置,如果没有xxx. 则返回-1 从右往左
// eg:截取字符串中的json部分
var a = '{ "name":"alex", "age":17, {"hobby":"zhuqiu"} }一堆其他的字符串'
a.substring(0, a.lastIndexOf('}')+1) // '{ "name":"alex", "age":17, {"hobby":"zhuqiu"} }'
s.toUpperCase() // 转换成大写字母
s.startsWith("xxx") // 判断是否以xxx开头
s.charCodeAt(i) // 某个位置的字符 对应 ascii码的 10进制 数字
// 相反:String.fromCharCode(n); 数字n 对应的ascii码的 字母
// js为了隐藏字符串本身(eg:字符串很重要,是加密解密的key),常用一些混淆代码
// eg:
// 混淆代码
var offset = 18;
// 中间再隔着很多其他障眼法的代码
var x = 115;
// 一系列神奇操作
x -= offset; // 115-18 = 96
x = String.fromCharCode(x);
console.log(x) // 'a'
// 源代码:上面实质就是
x = 'a'
// 再正常通过x 去加密
二、条件分支
2.1 if 判断
// 语法1:
if(条件1){
代码块1
}
// 解读:
当 条件1 成立时, 执行 代码块1中的内容
// 注:如果代码块1 中的内容只有一行. 则可以省略外面的大括号(一些逆向工程里会有)
if (条件1) 一行代码块1;
else 一行代码块2;
// 语法2:
if(条件1){
代码块1
} else {
代码块2
}
// 解读:
当 条件1 成立时, 执行 代码块1中的内容
若 条件1 不成立,则执行 代码块2中的内容
// 语法3:
if(条件1){
代码块1
} else if(条件2) {
代码块2
} else if(条件3) {
代码块3
} ... {
代码块n
} else {
代码块else
}
// 解读:
当 条件1 成立时, 执行 代码块1中的内容,
当 条件2 成立时. 则执行 代码块2中的内容
...
如果都不成立, 最终执行 代码块else 中的内容
2.2 switch语句
该语句是python中不存在的,但是在Java、C以及JS中依然会有使用
switch(变量){
case 值1:
代码块1
break // 可选
case 值2:
代码块2
break // 可选
case 值3:
代码块3
break // 可选
default: // 可选
default代码块
}
// 解读:
执行时, switch会判断变量的值 是否是 值1,
如果是, 则执行代码块1 以及代码块1中的break,
如果不是, 则继续判断 值2 ...
如果变量的值 都没有和 这些条件的值相等,则执行 default代码块
// 注意:
每一个 case 中都可以 选择或不选择 break
需要注意的是, 如果不写 break ,那么就会形成 case穿透现象
// eg: 变量的值 和值1 相等,并且case1中没有写 break
则在执行的时候. 会执行完 case1 中的代码块1
然后会自动穿透到后续所有 case中 去执行里面的代码块, 而不经过case中的条件验证
// case穿透 是语法机制,不是bug,作用可以简化case代码体中的代码
// eg:判断月份是上下半年
var a = 1;
switch(a){
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
console.log("上半年");
break;
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
console.log("下半年");
break;
}
三、循环语句
在js中有三种循环语句
3.1 while循环
while循环逻辑和python中的while几乎一模一样, 就是符号上有些许的区别
// 语法1:
while(条件){
循环体 -> 里面可以有break和continue等关键字
}
// 解读:
先判断 条件 是否为真, 如果真, 则再执行循环体
执行完循环体 , 会再次判断 条件 ....
循环中也可以使用 break 和 continue 等关键字,来控制循环的走向
// 语法2: 和
do{
循环体
} while(条件);
// 解读:
先执行循环体, 然后判断 条件是否成立, 如果成立,再来一次
注意:由于do..while是先执行的循环体. 所以, 不论条件如何, 至少执行一次 循环体
3.2 for 循环
// 语法1: for的第一种语法
for(表达式1; 表达式2; 表达式3){
循环体
}
// 解读:
for循环和python中的for循环是完全不一样的
首先, 在执行的时候, 先执行 表达式1
然后, 判断 表达式2 执行结果是否为真, 如果真 , 则执行循环体
再然后, 执行 表达式3
再然后, 判断 表达式2 执行结果是否为真 , 如果真, 则执行循环体
再然后, 执行 表达式3
.....
直到, 表达式2 得到的结果是 假, 则跳出循环
// eg: 用for循环来跑一个 1~99
for(var i = 1; i < 100; i++){
console.log(i);
}
// 解读:
首先, i = 1,
然后, 判断 i < 100 成立
打印i 1
再然后, i++, i变成2
再然后, 判断 i < 100 还是成立
打印i 2
再然后, i++, i变成3
再然后, 判断 i< 100 还是成立
打印i 3
....
// for循环的固定逻辑也就这样了 ***
for(变量声明; 条件判断; 改变变量){
循环体
}
// 语法2: for的第二种语法
var a = [11,22,33,44,55,66] // 数组
for(let i in a){ // in 后面放被遍历的对象 可以是 数组、对象(字典)
console.log(i + "_" + a[i])
}
// 这种写法 非常类似python中的for循环
// 注意:
这里的 i 是 数组a 的索引信息,若需要数据:a[i]
// 遍历数组 等价于: 语法1
for(var i = 0; i < a.length; i++){
console.log(i + "_" + a[i])
}
四、数组和对象
4.1 数组
在JS中创建数组非常简单. 直接[ ]
即可, 也可以用new Array()
,效果都一样
var as = [11,22,33,44,55];
// 通过方法声明的方式
var bs = new Array(11,22,33,44,55);
数组的常用操作
arr.length; // 获取数组长度
arr.push(data); // 添加数据 尾部追加
arr.pop(); // 删除数据, 从后面删除, 并返回被删除的内容
arr.shift() // 删除数据, 从前面删除, 并返回被删除的内容
// 遍历数组,去执行某个回调函数 *** 其实function函数 就是回调函数
数组中的每一项循环出来. 分别去调用function函数, 会自动的将 数据 传递给函数的第一个参数
arr.forEach(function(e, i){ // 第一个参数 e 是元素 (数据本身)
console.log(i+"__"+e); // 第二个参数 i 是可选的, 元素索引
});
for(let i in arr){
console.log(i+"__"+arr[i])
}
arr.join("连接符"); // 使用 连接符,将数组中的每一项拼接起来. 和python中的 "".join()雷同
4.2 对象
在JS中创建一个自定义对象非常容易. 和python中的字典几乎一样{ }
// js有很多种的对象,自定义对象 <===> python的字典
var p = {
name: "汪峰",
age: 18,
wife: "章子怡",
'wife': "ab", // key可以是变量,也可以字符串
chi: function(){ // value 也可以是函数
console.log(this.name , "吃饭") // this 类似于 self,代指当前局部空间(对象体内)
}
};
// 通过方法声明的方式
var p2 = new Object()
使用对象
p.name
p.age
// 对象的'.' 获取方法 和 对象的'[""]' 获取属性 是互通的,都可以使用
p['wife']
p.wife // 都可以取出来 注意:中括号形式,要引号,点形式 不加引号
p.chi() // 调用函数
p['chi']()
// 引申:恶心的混淆
var s = "吐啊吐啊就习惯了" // s是字符串类型的对象
var arr = s.split("") // 字符串.方法
var arr = s["split"]("") // 变相1:通过字符串["属性"],获取对象的方法函数,再() 调用
var arr = s["s" + "p" + "li" +"" + "t"]("") // 变相2:在变相1 上拓展 拆分字符串
var arr = s["s" + "p" + "li" +"" + String.fromCharCode(116)]("") // 变相3:在变相2 上拓展 字符串的ASCII码
从上述内容中几乎可以看到. JS对象的使用几乎是没有门槛的. 十分灵活
for(var n in p){
if(typeof(p[n]) != 'function'){
console.log(p[n])
}
}
五、函数(重点)
// 语法:
// 1 声明函数
function 函数名(形参1, 形参2, 形参3....){ // 没有函数名,就是匿名函数
函数体
return 返回值
}
// 2 调用函数
函数名(实参1, 实参2, 实参3....)
// 除了写法换了一丢丢. 其他的东西和python完全一致
// 3 函数的隐藏属性:arguments 参数,可以接受 传递到函数体的所有参数
// eg:
function func(){ // 不明确显示 形参,利用隐藏属性arguments,接受实参
console.log(arguments)
console.log(arguments[0], arguments[1])
};
func("alex", 18);
简单案例
function an(a, b){
return a + b
}
ret = an(1, 2)
console.log(ret); // 3
很简单,不是么? 那为什么,在网页上看到一些网站的JS是如此的复杂呢?
注意:JS其实没有一个非常严格的语法规则,只要能够形成xxx()
并且xxx是一个函数的话,就可以执行
例如:
// 函数的各种其他写法:
var an = function(a, b){
return a + b
}
an(1, 2) // an虽然是var声明的变量, 但是它指向是一个匿名函数. 那就可以执行
var $ = function(a, b){
return a + b
}
$(1, 2) // $没有被JS内置使用,就可以用啊 同理 '. _' 也OK
// 这个也很过分. 要拆开来看 第一个括号里面放的就是一个函数,所以依然可以执行.
(function(a, b){
return a + b
})(1, 2)
c = (function(){
var m = {
name:'alex',
age:'18',
xijiao: function(a){ console.log(a+"来帮我洗脚"); }
}
return m
})
c() // c 也可以执行
// ! + 等等也都可以,统称为自运行函数
// 主要作用于:某个单独js文件中,就是一个大的自运行函数,为了声明出一块局部空间(自运行函数体内)
!function(){}()
+function(){}()
^function(){}()
// 还有一个问题. 未来我们也会遇到的. 就是这个return
var an = function(){
return console.log("我爱你"), console.log("爱你妹"), "哈哈"
}
// 注意:
发现js会把return后的每一个','分割语句,都执行一次
但最终返回值,其实只是最后的那个 "哈哈"