js逆向学习(二)
tip 由于js逆向中需要对js有一定的了解,所以在正式尝试案例前需要对js的一些基础有一定了解,所以会用一定的篇幅去解释一些基础概念语句。
object对象
object对象的基本操作
Object 的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它们确实是非常理想的选择。
`创建 Object 实例的方式有两种。
1 | // |
- object可以通过. 和 []来访问。
1 | console.log(people.name) |
- object可以通过for循环遍历
1 | for (var attr in person){ |
通过构造函数和 new
关键字实现面向对象编程,展示对象的实例化、属性赋值和方法调用。尽管在 ES6+ 中更推荐使用 class
,但理解构造函数模式仍是掌握 JS 面向对象的基础。
1 | function person(name,age) { |
json序列化和反序列化
JSON
:JavaScript 对象表示法,是一种轻量级的数据交换格式。易于人阅读和编写。
- json是一种数据格式, 语法一般是{}或者[]包含起来
- 内部成员以英文逗号隔开,最后一个成员不能使用逗号!
- 可以是键值对,也可以是列表成员
- json中的成员如果是键值对,则键名必须是字符串.而json中的字符串必须使用双引号圈起来
// json数据也可以保存到文件中,一般以”.json”结尾.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var data = {
name: "xiaoming",
age: 22,
say: function(){
alert(123);
}
};
// 把对象转换成json字符串
var ret = JSON.stringify(data);
console.log(ret ); // {"name":"xiaoming","age":22}
// 把json字符串转换成json对象
var ret2 = JSON.parse(ret);
console.log(ret2);
Date对象
- 创建Date对象
1 | //方法1:不指定参数 |
- 获取时间信息
1 | 获取日期和时间 |
Math对象
1 | // Math对象的内置方法 |
JS中的函数(重点)
声明函数
1 |
|
函数调用
1 | //f(); --->OK |
不同于python,js代码在运行时,会分为两大部分———检查装载 和 执行阶段。
- 检查装载阶段:会先检测代码的语法错误,进行变量、函数的声明
- 执行阶段:变量的赋值、函数的调用等,都属于执行阶段。
函数参数
(1) 参数基本使用
1 | // 位置参数 |
函数返回值
在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。
1 | function add(x,y) { |
1、在函数体内可以包含多条 return 语句,但是仅能执行一条 return 语句
2、函数的参数没有限制,但是返回值只能是一个;如果要输出多个值,可以通过数组或对象进行设计。
作用域
作用域是JavaScript最重要的概念之一。
JavaScript中,变量的作用域有全局作用域和局部作用域两种。
- 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
- 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉
首先熟悉下var
1 | var name = "bobo"; // 声明一个全局变量 name并赋值”bobo“ |
作用域案例:
1 | var num = 10; // 在函数外部声明的变量, 全局变量 |
匿名函数
匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。
1 | // 匿名函数赋值变量 |
闭包函数
我们先看一段代码.
1 | let name = "周杰伦"; |
发现没有, 在函数内部想要修改外部的变量是十分容易的一件事. 尤其是全局变量. 这是非常危险的. 试想, 我写了一个函数. 要用到name, 结果被别人写的某个函数给修改掉了. 多难受.
接下来. 我们来看一个案例:
同时运行下面两组代码:
1 | // 1号工具人. |
1 | // 2号工具人 |
两组代码是在同一个空间内执行的. 他们拥有相同的作用域. 此时的变量势必是非常非常不安全的. 那么如何来解决呢? 注意, 在js里. 变量是有作用域的. 也就是说一个变量的声明和使用是有范围的. 不是无限的. 这一点, 很容易验证.
1 | function fn(){ |
直接就报错了. 也就是说. 在js里是有全局和局部的概念的.
直接声明在最外层的变量就是全局变量. 所有函数, 所有代码块都可以共享的. 但是反过来就不是了. 在函数内和代码块内声明的变量. 它是一个局部变量. 外界是无法进行访问的. 我们就可以利用这一点来给每个工具人创建一个局部空间. 就像这样:
1 | // 1号工具人. |
这样虽然解决了变量的冲突问题. 但是…我们想想. 如果在函数外面需要函数内部的一些东西来帮我进行相关操作怎么办…比如, 一号工具人要提供一个功能(加密). 外界要调用. 怎么办?
1 | // 1号工具人. |
注意了. 我们如果封装一个加密js包的时候. 好像还得准备出解密的功能. 并且, 不可能一个js包就一个功能吧. 那怎么办? 我们可以返回一个对象. 对象里面可以存放好多个功能. 而一些不希望外界触碰的功能. 就可以很好的保护起来.
1 | // 1号工具人. |
OK. 至此. 何为闭包? 上面这个就是闭包. 相信你百度一下就会知道. 什么内层函数使用外层函数变量. 什么让一个变量常驻内存.等等. 其实你细看. 它之所以称之为闭包~. 它是一个封闭的环境. 在内部. 自己和自己玩儿. 避免了对该模块内部的冲击和改动. 避免的变量之间的冲突问题.
闭包的特点:
- 内层函数对外层函数变量的使用.
- 会让变量常驻与内存.
变量提升(不正常现象)
看以下代码, 或多或少会有些问题的.
1 | function fn(){ |
发现问题了么. 这么写代码, 在其他语言里. 绝对是不允许的. 但是在js里. 不但允许, 还能执行. 为什么呢? 因为在js执行的时候. 它会首先检测你的代码. 发现在代码中会有name使用. OK. 运行时就会变成这样的逻辑:
1 | function fn(){ |
看到了么. 实际运行的时候和我们写代码的顺序可能会不一样….这种把变量提前到代码块第一部分运行的逻辑被称为变量提升. 这在其他语言里是绝对没有的. 并且也不是什么好事情. 正常的逻辑不应该是这样的. 那么怎么办? 在新的ES6中. 就明确了, 这样使用变量是不完善的. es6提出. 用let来声明变量. 就不会出现该问题了.
1 | function fn(){ |
**结论一, 用let声明变量是新版本javascript提倡的一种声明变量的方案. **
let还有哪些作用呢?
1 | function fn(){ |
显然一个变量被声明了两次. 这样也是不合理的. var本意是声明变量. 同一个东西. 被声明两次. 所以ES6规定. let声明的变量. 在同一个作用域内. 只能声明一次.
1 | function fn(){ |
注意, 报错是发生在代码检查阶段. 所以. 上述代码根本就执行不了.
结论二, 在同一个作用域内. let声明的变量只能声明一次. 其他使用上和var没有差别
js包的导入(exports)
类似Python中的模块导入
1 | // functions.js文件 |
1 | // main.js |