js逆向安全指南(1)-- 认识js的数据类型
不多废话,直接来
js的六种基本数据类型
- 数值:
- 整数,number,long
- 小数, float,double
- 字符串:
- string(文本)
- 布尔值
- boolean(true,false)
- undefined
- null
- 对象(Object)
- object
- array
- function
- Date
- String
- Number
- Boolean
查看类型
- typeof,返回一个值的数据类型,如果变量没有声明不会报错
- instanceof,表示对象是否为某个构造函数的实例
- Object.prototype.toString
typeof用法
instanceof用法
因为instanceof是针对对象而言的,所以下面我用整数1判断Number和Object会是false,且如果用未声明的变量做判断会报错
Object.prototype.toString用法
这个暂时可以不用管,后续会详细介绍的
null和undefined
null的类型是其实本质是Object,由于一些历史原因造成的,因为1995年js诞生是,只设计了对象,整数,浮点数,字符串,布尔值五种数据类型,并没有考虑null的情况,而只把他当作object的一种特殊值,后面才独立出来作为一种单独的数据类型。
不过为了兼容以前的代码,typeof null 会返回object也依然存在
null和undefined都可以表示“没有”,语法没有区别,在if判断里都是false,这也是一个历史遗留问题。
因为在初期的js是不包含错误处理机制的,同时初期的null值表示“无”的意思,根据C语言的传统,null会自动转为0,这样就不容易报错。
而后面有了错误处理机制以后,这样的设定就不行了,所以又诞生了undefined
目前而言,两者唯一的区别就是,null表示“空”对象,转为数值时是0,undefined表示“此处未定义”的原始值,转为数值则是NaN
布尔值为假的有
- undefined
- null
- false
- 0
- NaN
- "" 或 '' (空字符串)
注意:空数组[]和空对象{}对应的布尔值是true
数值
js里,所有的数字都是以64位浮点数形式存储的,即使原本是整数也会存储为浮点数,所以,1 和1.0是同一个数
也就是说,js的底层是根本没有整数的,所有的数字都是小数,而且是64位的小数,容易造成一个问题就是,某些运算只有整数才能完成的,js自动转成了64位浮点数,再转成32位整数,再进行计算,如果是大批量或者计算密集型的操作,就很耗时间,所以,在js里,如果算平方根或者立方根不会直接用运算符号或者相关数学的方程式计算,而是借用位运算的形式,位运算就会很快很多
因为,浮点数不是精确的值,涉及到小数的时候,容易导致与预期不一样的结果:
这种结果,你就说秀不秀吧
NaN
NaN是js的特殊值,表示“非数字”,主要出现在将字符串解析成数字出错的场合
NaN不是独立的数据类型,而是一个特殊数值,它属于Number,不等于任何值,包括它自己,它和任何数做运算得到的都是NaN
Infinity
Infinity表示“无穷”,用来表示一个正的数值太大(正向溢出overflow)或者一个负的数值太大(负向溢出underflow),就是数学里的"oo",由于这个值不会报错,所以单纯的数值运算几乎没有可能抛出异常
非0数除以0也会等于Infinity
Infinity大于一切数值(除NaN),-Infinity小于一切数值(除NaN)
Infinity与NaN比较为false
与数值相关的全局方法
parseInt():用于将字符串转为整数或者带有进制的数
parseFloat():用于将一个字符串转为浮点数
isNaN:判断是否为NaN
isFinite:返回一个布尔值,表示某个值是否为正常的数值
字符串
这个类型就跟python里的差不多的,唯一的区别就是使用的方法名不一样,反正就是用引号包裹住的就是字符串了,有个点需要注意的就是,js默认存储字符串是用的unicode编码,与python3一致
base64
浏览器里:
- btoa():任意值转为base64编码
- atob():base64编码还原
- 非ASCII码要转码再base64 encodeURIComponent,decodeURIComponent
nodejs:
var b64encode = new Buffer('JavaScript').toString('base64')
var b64decode = new Buffer(b64encode,'base64').toString()
Object对象
Object是js语言的核心概念,这个就跟python的object一个感觉了,就不多解释字面上的意思了
对象的每个键名又称为属性(property),如果某个属性也是对象的话,就可以再次访问其属性,比如 Object.prototype.toString
属性的查看:
Object.keys
属性的删除
delete
只能删除对象本身的属性,不能和三处继承来的属性,注意用Object.keys查看的时候,Object是首字母大写的
属性是否存在
- in
- hasOwnProperty
这里的hasOwnProperty可以理解为python里的hasattr
属性的遍历
for...in
太多了就不给完整的了
函数
函数就是一个可以服用的代码块而已,比如一个网站的个人信息获取功能,封装成一个函数profile,然后这个profile可以被用在登录接口里的用户信息获取,和会员等级判断,以及前端个人主页展示,这三个页面或者接口都会调用profile函数来获取用户信息
js里有三种声明函数的方法:
- function命令
- 函数表达式
- Function构造函数
第三个方式在浏览器的控制台里有这个问题,在node里是可以的:
js里函数的优先级是与其他数据类型地位平等
函数的属性和方法
这个没有太多需要注意的
name属性,length属性,toString()方法比较常用
函数的参数传递
js里函数的参数给定后,不一定一定要传入相对应的参数的,反正不会报错,只要真的给定了相对应的关键词参数个数之后,函数才会真的调用起来
函数的arguments对象
由于js允许函数有不定数目的参数,所以需要一种机制,可以在函数内部读取所有参数,这就是arguments对象的又来
arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,后面以此类推
通过arguments.length属性剋有判断函数实际调用时到底用了几个参数
arguments.callee属性返回其对应的原函数
arguments对象要想使用数组方法,将其转为数组再用
- Array.prototype.slice.call(arguments)
- for...in,然后push到一个数组里
函数立即调用
- var a = function a(){}(); // 必须带上分号
- (function(){})(); // 必须带上分号
- (function(){}()); // 必须带上分号
说白了就是,在定义完就会立即执行,这个在做js逆向的时候很多用立即调用的
数组
这个就相当于python里的列表了,然后数组里面什么都可以放
数组的遍历
如果数组里面有空值,会自动跳过,除了undefined
数据类型强制转换
- Number()
- String()
- Boolean()
这里给出来的都是做js逆向的时候需要注意的,其他的正向开发才会注意到的细节就不提了