20190528-JavaScriptの打怪升级旅行 { 语句 [ 赋值 ,数据 ] }
写在前面的乱七八糟:今天考了试,emmm很基础的题,还是Mrs房的面试题让人绝望啊┓( ´∀` )┏,补了很多知识,很综合的题,坑也很多,总的来说,查漏补缺,其实是啥都缺~
今天打的小BOSS主要是数据,但也不得不提到赋值,┓( ´∀` )┏
语句:声明 变量 赋值 数据;
3.赋值
在说赋值方式之前,需要先引入js的数值类型:基本类型和引用类型(boss4会细剖),下面我就假装都懂这俩个小怪的区别了,开始我一本正经的吹~,咳,一本正经地打怪升级了。
现象:
解析:莫得慌,一步步来,首先是基本类型,当 a 自增1 时,b没有受到影响,这是因为基本类型存放在栈区,按值访问,操作的是保存在变量内的实际的值
其次,是引用类型,当改变数组 a 时,b没有受到影响?? 难不成又被水了?莫得慌,先跳过看下个框框,调用了数组a的pop()方法,b受到了影响!
这是因为引用类型存放的方式:在栈中存放对象变量标示名称和该对象在堆中的存放地址,在堆中存放数据。
一脸大雾,出现上面现象是因为:a = [1,2] //改变的是a引用本身,而非其数组对象,a 和 b 是毛线关系都么有的,而a.pop( );//在 b 指向数组对象后,调用pop( ) 方法改变了原有的数组对象,所以第一次操作 b 么有影响,而第二次却有,操作的是该对象在堆中的存放地址。
3.1传值赋值
var a = 基本类型
3.2引用赋值
var a = 引用类型
若仍旧一脸大雾,看图看图 =>
上图可见,基本类型,操作具体的值,b 同样是被赋值了10,而引用类型,操作对象的地址,当改变对象[1,2]的时候,b 也会随之而改变 ,但若只改变 a 自身,对 b 是免疫的,因为 b 引用的是 a 的地址而不是a 本身呐~
综上,第一章BOSS:语句 の 第三层boss:赋值,完结撒盐┓( ´∀` )┏
4.数据
4.1数据类型
4.1.1原始类型(primitive type)
4.1.1.1布尔值(boolean)
- true(真)
- false(假)
4.1.1.2数字(number)
- 所有数字都以64位浮点数形式储存
- 整数
- 浮点数/小数
- NaN
- 表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合
- NaN不等于任何值,包括它本身 NaN === NaN // false
- Infinity
- 表示“无穷”
- 一个正的数值太大,或一个负的数值太小,无法表示;
- 另一种是非0数值除以0
- Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)
- 表示“无穷”
- 数值精度
- 数值范围
- 如果一个数大于等于2的1024次方,那么就会发生“正向溢出”
- 即 JavaScript 无法表示这么大的数,这时就会返回Infinity
- Math.pow(2, 1024) // Infinity
- 如果一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”
- 即 JavaScript 无法表示这么小的数,这时会直接返回0
- Math.pow(2, -1075) // 0
- Number.MAX_VALUE // 1.7976931348623157e+308
- Number.MIN_VALUE // 5e-324
- 数值的表示法
- 字面形式直接表示
- 35(十进制)
- 0xFF(十六进制)
- 科学计数法表示
- 123e3 // 123000
- 123e-3 // 0.123
- 字面形式直接表示
- 数值的进制
- 十进制:没有前导0的数值
- 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值
- 十六进制:有前缀0x或0X的数值
- 二进制:有前缀0b或0B的数值
- API
- 转整数:parseInt('123') // 123
- parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN
- 如果字符串头部有空格,空格会被自动去除:parseInt(' 81') // 81
- 如果parseInt的参数不是字符串,则会先转为字符串再转换:parseInt(1.23) // 1
- 单个字符依次转换,若遇到不能转为数字的字符,跳出并返回已经转好的部分:parseInt('15px') // 15
- 若字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
- parseInt方法还可以接受第二个参数([2,36]),表示被解析的值的进制,返回该值对应的十进制数
- 默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制
- parseInt('1000', 2) // 8 ; parseInt('1000', 6) // 216 ; parseInt('1000', 8) // 512;
- 若第二个参数超出[2,36],则返回NaN parseInt('10', 37) // NaN
- 若第二个参数是0、undefined和null,则直接忽略 parseInt('10', undefined) // 10
- 转浮点数:parseFloat('3.14') // 3.14
- 判断值是否为NaN:isNaN(NaN) // true
- isNaN(NaN)
- function myIsNaN(value) { return value !== value; } =>利用NaN为唯一不等于自身的值
- 判断值是否为无穷大:
- isFinite(null) // true
- isFinite(Infinity) // false
- isFinite(-Infinity) // false
- isFinite(NaN) // false
- isFinite(undefined) // false
- 转整数:parseInt('123') // 123
4.1.1.3字符串(string)
- " "/ ' '
- 单双引号可以相互嵌套 'key = "value"' "It's a 'long' journey"
- 单嵌套单,双嵌套双,需要转义。'Did she say \'Hello\'?'
- 转义
- 反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符
- \0 :null(\u0000)
- \b :后退键(\u0008)
- \f :换页符(\u000C)
- \n :换行符(\u000A)
- \r :回车键(\u000D)
- \t :制表符(\u0009)
- \v :垂直制表符(\u000B)
- \' :单引号(\u0027)
- \" :双引号(\u0022)
- \\ :反斜杠(\u005C)
- 字符串可被视为字符数组,可使用数组的方括号运算符,用来返回某个位置的字符(位置编号从0开始)
- 方括号中的数字超过字符串的长度,或者方括号中根本不是数字,则返回undefined。'abc'[3] // undefined
- length属性返回字符串的长度
- Unicode 字符集
- Base64 转码
- 文本里面包含一些不可打印的符号,比如 ASCII 码0到31的符号都无法打印出来
- 以文本格式传递二进制数据,那么也可以使用 Base64 编码
- btoa():任意值转为 Base64 编码
- atob():Base64 编码转为原来的值
- var string = 'Hello World!';
- btoa(string) // "SGVsbG8gV29ybGQh"
- atob('SGVsbG8gV29ybGQh') // "Hello World!"
- 将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节
- btoa(encodeURIComponent('你好'));// "JUU0JUJEJUEwJUU1JUE1JUJE"
- decodeURIComponent(atob('JUU0JUJEJUEwJUU1JUE1JUJE'));// "你好"
4.1.1.4未定义undefined & 空null
- 同:undefined == null // true
- 异:null转为数字时,自动变成0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN;
- Number(null) // 0 5 + null // 5 ;Number(undefined) // NaN 5 + undefined // NaN;
4.1.1.5类型symbol
4.1.2引用类型/类(class)
4.1.2.1狭义的对象(object)
一组“键值对”(key-value)的集合
- 键名 /“属性”(property)
- 对象的属性之间用逗号分隔,最后一个属性后面可以加逗号(trailing comma),也可以不加
- 属性的读取var obj = { p: 'Hello World' };
- 使用点运算符obj.p // "Hello World"
- 使用方括号运算符obj['p'] // "Hello World"
- 属性的赋值 var obj = {};
- obj.foo = 'Hello';
- obj['bar'] = 'World';
- 属性的查看var obj = { key1: 1, key2: 2 };
- Object.keys(obj); // ['key1', 'key2']
- 属性的删除var obj = { p: 1 };
- delete obj.p // true
- 删除一个不存在的属性,delete不报错,而且返回true
- var obj = {}; delete obj.p // true
- 只能删除对象本身的属性,无法删除继承的属性
- 属性是否存在:in 运算符
- 用于检查对象是否包含某个属性(注意,检查的是键名,不是键值)
- 左边是一个字符串,表示属性名,右边是一个对象。
- var obj = { p: 1 }; 'p' in obj // true 'toString' in obj // true
- 问题:不能识别哪些属性是对象自身的,哪些属性是继承的
- 解决:对象的hasOwnProperty方法判断一下,是否为对象自身的属性
- 属性的遍历:for...in 循环
- for...in循环用来遍历一个对象的全部属性
- 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性
- 它不仅遍历对象自身的属性,还遍历继承的属性
- 键值:任何数据类型
- 如果一个属性的值为函数,通常把这个属性称为“方法”
4.1.2.2数组(array)
- 定义:按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示
- 任何类型的数据,都可以放入数组=>数组的元素还是数组,就形成了多维数组
- 本质:属于一种特殊的对象
- 属性:length 属性:返回数组的成员数量
- 运算符:in 运算符:检查某个键名是否存在
- 遍历:for...in循环
- 问题:不仅会遍历数组所有的数字键,还会遍历非数字键
- 解决:for循环/while循环/forEach( )
- 空位
- 当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole)
- 数组的空位是可以读取的,返回undefined
- 使用delete命令删除一个数组成员,会形成空位,并且不会影响length属性
- 问题:length属性不过滤空位=>使用length属性进行数组遍历,一定要非常小心
- 解决:forEach方法、for...in结构、以及Object.keys方法进行遍历,空位都会被跳过
- API
- Object.keys(arr):返回数组的所有键名
- 类数组(array-like object)
- 一个对象的所有键名都是正整数或零,并且有length属性
- 这种length属性不是动态值,不会随着成员的变化而变化
- 数组的slice方法可以将“类似数组的对象”变成真正的数组var arr = Array.prototype.slice.call(arrayLike)
- call()把数组的方法放到对象上面function print(value, index) { console.log(index + ' : ' + value); } Array.prototype.forEach.call(arrayLike, print);
- 比直接使用数组原生的forEach要慢=>最好还是先将“类似数组的对象”转为真正的数组,然后再直接调用数组的forEach方法
4.1.2.3函数(function)=>第一等公民
- 函数的声明
- function命令
- 函数表达式(变量赋值)
- Function构造函数(new)
- 函数名的提升
- 函数的属性
- name:返回函数名/函数表达式名
- length:返回函数预期传入的参数个数,即函数定义之中的参数个数
- 函数的API
- toString:返回一个内容是函数的源码的字符串
- 函数作用域
- 定义:变量在声明它们的函数体以及这个函数体嵌套的任意函数体都是有定义的
- 函数内部的变量提升
- 函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域=>"闭包"现象
- 参数
- 参数的省略
- 被省略的那个为undefined
- 如果一定要省略靠前的参数,只有显式传入undefined f(undefined, 1) // undefined
- 传递方式
- 原始值(数值、字符串、布尔值):传值传递(passes by value)=>在函数体内修改参数值,不会影响到函数外部
- 引用值(数组、对象、其他函数):传址传递(pass by reference)=>在函数内部修改参数,将会影响到原始值
- 同名参数
- 若有同名的参数,则取最后出现的那个值
- 若没有提供第二个参数,则取值=undefined=>若要获得第一个a的值,可以使用arguments对象
- arguments 对象
- JS允许函数有不定参=>arguments对象用于在函数体内部读取所有参数
- 正常模式下,arguments对象可以在运行时修改
- 严格模式下,arguments对象与函数参数不具有联动关系
- callee 属性:返回它所对应的原函数(严格模式里面是禁用的,因此不建议使用)
- 参数的省略
- 闭包(closure)
- 作用
- 可以读取函数内部的变量
- 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在
- 封装对象的私有属性和私有方法
- 劣势
- 外层函数每次运行=>一个新的闭包=>保留外层函数的内部变量=>内存消耗很大=>不能滥用闭包=>网页的性能问题
- 作用
- 立即调用的函数表达式(IIFE)
- 目的
- 不必为函数命名,避免了污染全局变量
- IIFE 内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
- 原理
- 写法
- 目的
- eval 命令
- 接受一个字符串作为参数,并将这个字符串当作语句执行
- 不能用来与eval以外的命令配合使用
- 没有自己的作用域,都在当前作用域内执行,因此可能会修改当前作用域的变量的值,造成安全问题
- =>如果使用严格模式,eval内部声明的变量,不会影响到外部作用域
- 即使在严格模式下,eval依然可以读写当前作用域的变量=>安全风险依然存在
- eval的本质是在当前作用域之中,注入代码=>安全风险和不利于 JavaScript 引擎优化执行速度=>不推荐使用
- eval最常见的场合是解析 JSON 数据的字符串=>使用原生的JSON.parse
4.1.3类型判断
4.1.3.1typeof 运算符
- typeof 123 // "number"
- typeof '123' // "string"
- typeof false // "boolean"
- typeof undefined // "undefined"
- typeof null // "object"
- typeof window // "object"
- typeof {} // "object"
- typeof [] // "object"
- function f() {} typeof f // "function"
- typeof v // "undefined"
4.1.3.2instanceof 运算符
4.1.4类型转换
4.1.4.1隐式转换
- 数字 + 字符串:数字会被转成字符串 10 + 'kb' //'10kb'
- 数字 + 布尔值:布尔值会被转换数字 true->1/false->0 1 + true //2
- 布尔值 + 布尔值:布尔值会被转成数字 true->1/false->0 true + false //1
- 布尔值 + 字符串:布尔值会被转成字符串 true + 'abc' //'trueabc'
4.1.4.2强制转换
- 强制转换成整型parseInt('23.55t'); // 23
- 强制转换成浮点型parseFloat('23.55t'); //23.55
- 转换成数字Number('23.55'); //23.55
- 原始值
- 字符串==>数字
- 能解析为数值=数值
- 不能解析为数值=NaN(只要有一个字符无法转成数值,整个字符串就会被转为NaN)
- 空字符=0
- 布尔值==>数字
- true=1
- false=0
- undefined==>数字
- undefined=NaN
- null==>数字
- null=0
- 字符串==>数字
- 引用值=>NaN
- 原始值
- 转换成字符20.toString() // '20'
- 转换成布尔值Boolean()
- undefined=false
- null=false
- 0(包含-0和+0)=false
- NaN=false
- ''(空字符串)=false
- 其他=true
4.2数据表现形式
4.2.1值
4.2.1.1原始值
4.2.1.1.1布尔值(boolean)
4.2.1.1.2数字(number)
4.2.1.1.3字符串(string)
4.2.1.1.4未定义undefined
4.2.1.1.5空null
4.2.1.2引用值
4.2.1.2.1普通对象/标准对象{ }
4.2.1.2.2数组对象[ ]
4.2.1.2.3函数对象funtion( ){ }
- 定义
- 作用
- 调用
- 形参 & 实参
- 封装函数
4.2.1.2.4正则对象/ /
4.2.2表达式(Expression)
表达式:运算元+运算符=运算结果
4.2.2.1运算符
- 算术运算符
- 加 +
- 减 -
- 乘 *
- 除 /
- 取余 %
- 自增 ++
- 自减 --
- 逻辑运算符
- 与 &&
- 或 ||
- 非 !
- 关系(比较)运算符
- 大于 >
- 小于 <
- 大于等于 >=
- 小于等于 <=
- 等于 ==
- 全等于 ===
- 不等于 !=
- 不全等于 !==
- 赋值运算符
- 等于 =
- 加等 +=
- 减等 -=
- 乘等 *=
- 除等 /=
- 取余等 %=
- 条件(三目)运算符
- 条件?真:假
- ps:一目就是只有一个操作数或者表达式++
- 二目运算符就是含有两个操作数或者表达式<=
- 三目运算符是含有三个操作数或者表达式 条件表达式 ? 表达式1 : 表达式2
- 逗号运算符
- 可以在一条语句中执行多个运算
- 常用变量声明中
- var iNum1 = 1, iNum = 2, iNum3 = 3;
- 对象运算符
4.2.2.2运算顺序 => 优先级
- 优先级高的运算符先执行,优先级低的运算符后执行
- 圆括号:优先级是最高的,即圆括号中的表达式会第一个运算
- 不是运算符,而是一种语法结构
- 一种是把表达式放在圆括号之中,提升运算的优先级
- 另一种是跟在函数的后面,作用是调用函数
- 不具有求值作用,只改变运算的优先级
综上,第一章BOSS:语句 の 第四层boss:数据,完结撒盐┓( ´∀` )┏,因为数据里面还有几个大boss没清理,像数组/字符串/正则等的属性及API使用,需另开一章~
小结:附上第一章:语句的大纲笔记