本人以下大部分的知识结构来自于《javascript权威指南》,技术渣渣热爱前端,喜爱探索前端技术。
JS具体实现可能定义独有的全局变量和函数,每一种特定的JS运行环境都有自己的一个全局属性列表。
编程语言的基本特性:支持多种数据类型。变量的工作机制。
JS数据类型分为两类:原始类型 和 对象类型。
原始类型:数字:Number、字符串:String、布尔值:Boolean。
原始值:null:Null、undefined:Undefined。这两个值分别代表了各自特殊类型的唯一成员。
对象类型:普通对象:Object、特殊对象--数组:Array、函数:Function。
根据可变性来分(类型的值可以修改):可变类型:对象 数组。 不可变类型:数字,布尔值,字符串,null,undefined。
JS变量是无类型的。可以赋予任何类型的值。
JS采用词法作用域。函数外定义的变量--全局作用域--全局变量。函数内定义的变量--局部作用域或者函数作用域--局部变量。
数字:
ES6不支持8进制。在实际中应该尽量避免使用8进制。科学计数法属于浮点型直接量。
常用Math对象的一些方法和差别:
Math.round():标准四舍五入。例子:0.6--1·······1.1--1
Math.ceil():向上求整。例子:0.6 -- 1······1.2--2
Math.floor():向下求整。例子:0.6--0······1.2--1
Math.max():取最大值。
算术运算有三种特殊情况:溢出。下溢。被0整除。
溢出:结果大于JS最大数字上限(负数超过负数最大上限) -- Infinity 和 -Infinity
下溢:结果无限接近于0 而且比+-5×10的-324还小的情况 返回0。
被0整除:Infinity 和 -Infinity 0/0--NaN
ES3中Infinity 和 NaN可读可修改。ES5修改为只读。
NaN特殊性质:和任何值不相等,包括自身。可以用x!=x来判断这个全局变量。
JS浮点数采用的是二进制表示法,可以精确表示分数。然而我们常用的是十进制表示法的分数。所以浮点数的计算会有点小误会。
例子:JS中0.3 - 0.2 不等于 0.1.因为:0.3 -0.2 = 0.099999999999998;
字符串:
一组由16位值组成的不可变的有序序列。每个字符来自Unicode字符集。字符串长度是其所含16位值的个数。
字符串是固定不变的。这点必须反复重申。类似于replace(),toUpperCase()的方法都只是返回一个新字符串,原来的字符串不改变。
布尔值:
布尔值指代真或假,开或关,是或否。这个类型只有两个值:true 和 false;
比较语句里面的结果通常都是布尔值。
布尔值最常用在控制结构中。
有两个概念:真值。假值。
false,undefined,null,0,-0,NaN,""(空字符串)这七个值可以转换成false的值有时被称作“假值”,在比较语句中常常会进行隐式转换。
除了以上这些假值的值(包括对象和数组)都可以转换成true,被叫做“真值”。
布尔值也有运算符。&&,||,!
&&逻辑与。两个操作数都为真值才返回true;
||逻辑或。两个操作数其中一个为真值就返回真。
!逻辑非。一元操作符。返回操作数的相反的布尔值。
null和undefined:
null是JS的关键字,代表一特殊值,用于描述“空值”。typeof null = object。因为null被当作一个特殊的对象值。意思是空对象。其实null是很包罗万象的。
可以把它当作他自有类型的唯一值。表示数字,字符串,对象是“无值/空值”的。
第二个表示值的空缺为undefined。用未定义的值表示更深层次的“空值”。表示变量未定义,未初始化。属性或者元素不存在。函数没有返回值,他是一个
预定义的全局变量,不是关键字。这是和null不一样的地方。
typeof undefine = undefined 表示这个值是这个类型的唯一成员。
==操作符认为这两者相等。要用严格相等===来判断他们两个。
如果你希望把他们作为参数传入函数,最佳选择是使用null。
全局对象:
JS中非常重要且特殊的对象。看不见摸不着,但我们大多时候都在使用全局对象。全局对象的属性是全局定义的符号,JS可以直接使用。JS解释器启动时,他就自动创建一个新的全局对象,并给他定义一组初始化属性。
全局属性:undefined,Inifinity,NaN等
全局函数:isNaN(),parseInt(),eval()等
构造函数:Date(),String(),Object()等
全局对象:Math,JSON等(这里的全局对象可以看作真正全局对象的属性)
在代码的顶级(不在任何函数内部)的this 可以引用全局对象。
在客户端的JS环境中,在表示浏览器窗口的中的所有JS代码,Window对象充当了全局对象,应该说是全局对象的代理人。Window对象的window属性用来引用这个对象。可以代替this来引用全局对象。Window对象除了定义核心全局属性(就是上面列出的那些),还针对Web浏览器和客户端JS定义了一少部分其他的全局属性,可以说是一种补充。
初次创建时,全局对象定义了JS中所有的预定义值,让我们在一开始就可以使用一些属性值,方法啊,如同他帮我们把一间别墅的地基打好了,材料也提供好了,后面怎么建造房子就看我们自己的创造了。另外。代码声明了一个全局变量就自动成为全局对象的属性。后面访问这个变量如同访问全局变量的属性。这就是上面说的我们看不见把摸不着但大多时候都在使用全局对象,毕竟我们都需要定义变量来编程。
包装对象:
JS对象是一种复合值。名值对的无序集合。
包装对象并没有名字那么神奇。他用来解释了例如字符串直接量和数字直接量,布尔直接量。不是对象但又拥有方法来操作这个直接量的现象。
原因是:但我们引用了字符串的属性,如x.substring()。那么后台会在这个方法运行之前调用new String(x)来转成对象,这个对象就拥有了字符串的方法,并用来处理属性或者方法的引用。一旦这个属性或者方法引用结束。那么这个调用的new String(x)自动销毁。(其实实际上后台的工作并不一定是创建或者销毁了这个临时对象,然而整个过程在开发者看来是这样。)具体他是怎么的一个过程我们可以不用去追究,我们只要这样理解就行了。
另外:不推荐使用直接量的使用形式如:“123”.substring()。应该先赋给一个变量让变量来使用这个方法。
因为这个包装对象是临时的。引用结束后就销毁或者消失,之后即使给这个对象定义属性或者方法后面都无法访问,因为毕竟消失了嘛。
存取字符串,数字,布尔值,的属性时创建的临时对象叫做包装对象。偶尔拿来区分真正的字符串数字布尔值对象。包装对象是一种实现的细节。因为这些直接量的属性都是只读的,不能附加新的属性,这是和对象的差距所在。
当然也可以显示的创造包装对象。在你的代码而不是后台帮你调用 new String(x)。虽然并不推荐这么做。
原始值和可变对象的引用:
JS原始值:undefined,NaN,布尔值,数字,字符串。(不可变)
JS对象:数组,函数(可变)
任何方法不能改变原始值,就像我一样,经历任何事情,我还是我,是不可变的,不会变成张三李四或者谁。
数字和布尔值的概念更显然。数字1 他就是1 不能改变值为1 的值,不能把1 说成值10.对吧。字符串看起来好像可以改变其中的值。
因为字符串的特性s=“abc"。你可以通过s[0]=a索引的方式访问,但是仅限于此。s[0] = c是禁止的。
原始值和原始值的比较是值与值的比较。
值相等时他们才相等。字符串的比较相对复杂一些。长度相等索引上的字符相等才相等。
对象的比较是按引用比较。o, p两个对象拥有相同的方法和属性 但是不相等。a,b两个数组有相同元素但是不相等。
这就是为什么对像也称为引用类型的原因。以此来区分JS基本类型。当且仅当引用的是同一个对象 他们才相等。例子。var a = [1];var b = a;a===b--true;
这样只是出于比较的意图。假如想要复制一个对象但是又不能相关应该采取循环遍历重新造一个对象。
类型转换:
类型转换是JS非常神奇的地方。JS期望使用一个布尔值的时候,可以提供任意类型的值例如真值和假值:null,undefined,0,-0,"",NaN。 JS根据需要自行转换类型,
这一块是隐式的我们看不见的转换。
值 | 转换成字符串 | 数字 | 布尔值 | 对象 |
undefined null |
"undefined" "null" |
NaN 0 |
false false |
throw TypeError throw TypeError |
true false |
"true" "false" |
1 0 |
new Boolean(true) new Boolean(false) |
|
"" "1.2" "abc" |
0 1.2 NaN |
false true true |
new String(""); new String("1.2"); new String("abc"); |
|
-0 0 NaN Inifinity -Inifinity 1 |
"0" "0" "NaN" "Infinity" "-Inifinity" "1" |
false false false true true true |
new Number(值) | |
{} [] [1] ['a'] function(){} |
toString "" "1" join 函数具体实现的代码 |
valueOf 0 1 NaN NaN |
true true true true true |
数字转换情况 有Number, parseInt, parseFloat的转换规则。
字符串的转换有String, toString规则
对像转换成值有toString和valueOf的规则。可以看看之前转型函数那篇。
转换:
相等运算符==会将操作数进行转换再比较,===在判断相等时不做任何类型转换。
很多时候JS自动类型转换。有时也需要显示转换。
最简单的方法:Boolean(),Number(), String(),Object().不通过new调用时会作为类型转换函数并按照上述表格规则进行类型转换。
例子Number("2") -- 2;String(2)--"2";
除了/null undefined 之外的任何值都具有toString方法。这个方法的执行结果通常和String一致。要转换null 和undefined通常用String();
如果试图把null undefine转换为对象,会抛出一个类型错误。Object(null/undefined)仅仅简单返回一个新创建的空对象。
JS运算符经常做隐士的类型转换。二元操作符+ :一个字符串 一个数字 则把数字转换为字符串
一元操作数 +:+x等价于Number(x)。
一元操作数!:将其操作数转换为布尔值。!!x等价于Boolean(x)
Number类的toString()可以接受转换基数。例如:var n = 8; n.toString(2)--1000;
处理Number类的浮点型到字符串的过程。Number类提供了三个方法用于不同的场景。
toFixed(x) 根据x的数值取多少位小数。例子:var n = 1.23 n.toFixed(0)--1;
toExponential(x)根据x的数值使用指数计数法。例子:var n = 12354.7899 n.toExponential(1)--1.2e4
toPrecision(x)根据x的数值取有效位数。有效数比x多一位。例子: var n = 12345.6789 n.toPrecision(4)--1.2345e4。 n.toPrecision(7)--12345.67
通过Number()传入一个字符串,他会试图将其转换为一个整数或浮点数。但是只能基于10进制,并且不能出现非法的尾随字符。只要存在一个字母返回NaN;
parseInt 和parseFloat是Number()的进化版 更加灵活人性。
parseInt可以解析整数。parseFloat可以解析整数和浮点数。
ES3可解析8进制。ES5除非指定位数否则不解析8进制。parseInt parseFloat跳过任意数量的前导空格。如果第一位就遇到非法数字,返回NaN;
parseInt可以接受第二个参数。用来指定数字转换基数,合法的取值范围是2-36;例子:parseInt("11",2)--3。以2进制的标准解析11;
对象转换成原始值:
对象到字符串和对象到数字的转换通过调用待转换对象的一个方法来实现。但是,对象有两个不同的方法。而且场景不同更加复杂化。另,这里的字符产和数字的转换规则只能使用于本地对象,宿主对象根据各自的算法可以转换成字符串和数字。
所有对象继承自两个转换方法。toString用来反映这个对象的字符串。
很多类定义了特定版本的toString方法。例如数组类。[1,2,3].toString()--"1,2,3";
另外的还有valueOf。如果存在原始值则返回,然而对象大多无法真正表示为一个原始值,因此这个方法简单返回对象本身。
Date类的valueOf和getTime方法返回的一致。
通常我们用这两种方法进行对象到字符串和数字的转换。
但是特殊情况下JS执行完全不同的对像到原始值的转换。
JS对象到字符串的步骤:
如果对象具有toString,则调用这个方法。如果返回一个原始值,JS将这个原始值转换为字符串(如果本身不是字符串的话),并返回这个字符串作为结果。
转换成字符串的规则按照上述表格。
如果没有这个方法,或者没有返回一个原始值。那么会调用valueOf,如过存在则调用,如果返回原始值则把这个值转为字符串返回。(如果本身不是字符串)
到了这一步如果不存在这个方法 或者 不能得到一个原始值。则抛出类型错误。
JS对象到数字的步骤:
如果对象具有valueOf,则调用这个方法。如果返回一个原始值,JS将这个原始值转换为数字(如果本身不是数字的话),并返回这个数字作为结果。
转换成数字的规则按照上述表格。
如果没有这个方法,或者没有返回一个原始值。那么会调用toString,如过存在则调用,如果返回原始值则把这个值转为数字返回。(如果本身不是字符串)
到了这一步如果不存在这个方法 或者 不能得到一个原始值。则抛出类型错误。
这个可以解释空数组转换为数字0以及单个元素的数组同样会转换成一个数字。数组继承了默认的valueOf,这个方法返回一个对象而非原始值,所以进行第二步toString。空数组转换为空字符串,空字符串转换为数字0,单个元素的先转换为字符串再转换为数字。
+运算符会有特殊情况,假如+运算的一个操作数是对象,JS将使用特殊的方法转换成原始值,而不是使用其他运算符的方法执行对象到数字的转换,==运算符与此类似。
如果将对象和一个原始值进行比较,则转换将会按照对象到原始值的转换方式进行。
+ 和 == 应用的对象到原始值的转换包含日期对象的特殊情况。对于非日期类:基本上是对象到数字的转换,先valueOf,,日期则是先字符串的转换模式。而且通过valueOf个toString返回原始值不进行数字或者字符串的转换直接返回原始值。
<运算符也特殊。:任何对象都先进行到数字的转换。这个运算符也是直接返回原始值。
+ == !=和关系运算符是唯一执行这种特殊字符串到原始值的转换方法的运算符。其他运算符都很明确,而且对日期类也没有特殊情况。
例如- 把操作数都转换为数字。
简言之: + ==都要按照非日期先valueOf 转换数字开始,如果是日期类则相反。并且返回原始值不转换。
< 不管是不是日期类,都要先valueOf转换数字开始,并且也不转换原始值。