原生函数
常用的原生函数
String()
Number()
Boolean()
Array()
Object()
Function()
RegExp()
Date()
Error()
Symbol()
内部属性 [Class]
所有typeof 返回值为object 的对象都包含一个内部属性[Class],这个属性无法直接访问,一般通过Object.prototype.toString(..) 来看。
例如:
Object.prototype.toString.call([1,2,3]);
// "[object Array]"
基本类型值
Object.prototype.toString.call(null);
// "[object Null]"
封装对象包装
由于基本类型值没有.length 和 .toString() 这样的属性和方法。
封装对象释疑
想要自行封装基本类型值,可以使用Object(..)(不带new 关键字)
var a = "abc";
var b = new String(a);
var c = Object(a);
一般不推荐直接使用封装函数
拆封
封装对象中的基本类型值,可以使用valueOf() 函数。
var a = new String("abc");
var b = new Number(42);
var c = new Boolean(true);
a.valueOf(); // "abc"
b.valueOf(); // 42
c.valueOf(); // true
原生函数作为构造函数
Array(..)
var a = new Array(1,2,3);
a; // [1,2,3]
var b = [1,2,3]
b; // [1,2,3]
构造函数Array(..),不要求必须带关键字new,不带时他会自动补上Array构造函数只带一个参数时候,该参数会被数组的预设长度而不是当数组中的一个元素。
var a = new Array(3);
a.length; // 3
a;
总之永远不要创建和使用空单元数组
Object(..) , Function(..) , 和RegExp(..)
除非万不得已,否则不要使用Object(..) / Function(..)/ RegExp(..)
Date(..) 和Error(..)
创建时间必须使用 new Date(),主要是用来获取当前的Unix 时间戳Date.new()然后通过日期对象中的getTime() 来获得。
创建错误对象(error objec) 主要是为了获得当前运行的上下文。
Symbol(..)
基本数据类型——符号。符号具有唯一性的特殊值,用它来命名属性不容易导致重名。
Symbol 的静态属性形式,Symbol.create, Symbol.iterator
obj[Sybol.iterator] = function() {/*..*/}
使用 Symbol(..) 原生构造函数来自定义符号,不能带new 关键字,否则报错。
var mysym = Symbol("my own symbol");
mysym; // Symbol(my own symbol)
mysym.toString(); // "Symbol(my own symbol)"
typeof mysym; // "symbol"
var a = { };
a[mysym] = "foobar";
Object.getOwnPropertySymbols(a);
// [Symbol(my own symbol)]
原型类型
原生构造函数有自己的 .prototype对象 如: Array.prototype,
String.prototype.
String#indexOf(..)
在字符串中查找指定字符串的位置。
String#charAt(..)
获得字符串指定位置上字符
String#substr(..),String#substring(..) 和String# slice(..)
获取字符串的指定部分
String#toUpperCase() 和 String#toLowerCase()
将字符串转换为大写和小写
String#trim()
去掉字符串前后的空格,返回新的字符串
强制类型转换
值的类型转换
将值从一种类型转换为另一种类型转换,这是显示的情况,隐式的情况通常为强制类型转换。
JavaScript 中的类型转换总是是返回标量基本类型。
抽象值操作
ToString
抽象操作ToString ,它负责处理非字符串到字符串的强制类型转换数组的默认toString() 方法经过重新定义,将所有的单元字符串化以后在连接在一起。
var a = [1,2,3];
a.toString(); // "1,2,3"
JSON字符串换,
JSON.stringify(..) 在对象中遇到undefined,function 和 symbol 时会自动将其忽略,在数组中则会返回null。
例如:
JSON.stringify(undefined); // undefined
JSON.stringify(function(){}); // undefined
JSON.stringify(
[1,undefined,function(){},4]
); // "[1,null,null,4]"
JSON.stringify(
{a:2,b:function(){}}
); // "{"a":2}"
toJSON() 返回的应该是一个适当的值,可以是任何类型,然后再由JSON.stringify(..) 对齐进行字符串化。
ToNumber
有时候需要将非数字值当做数字来使用,比如数学运算。
true 转为 1, false 转换为 0 ,undefined 转换为NaN
null 转换为0
为了将值转换为相应的基本类型,抽象操作ToPrimitive ,首先检查该值是否有valueOf() 方法,如果有就用该值进行强制类型转换。没有就用toString()
的返回值来进行强制类型转换。如果valueOf() 和toString() 均不会返回值就会产生TypeError 错误。
ToBoolean
假值:
值可以被分为以下两类。
1.可以被强制类型转换为false的值
2.其他(被轻质类型转换为true的值)
以下这些是假值
undefined
null
false
+0,-0和NaN
""
假值对象:浏览器在某些特定情况下,在常规JavaScript语法基础上创建了一些外来值,这些就是 “假值对象”
真值
真值就是假值列表以外的值
显式强制类型转换
字符串和数字之间的显示转换
字符串和数字之间显示强制类型转换是通过String(..) 和Number(..).
两者之间的显式强制类型转换
var a = 42;
var b = String(a);
var c = "3.14";
var d = Number(c);
b; // "42"
d: // 3.14
还有其它方式实现字符串和数字之间的显示转换
var a = 42;
var b = a.toString();
var c = "3.14";
var d = +c;
b; // "42"
d: // 3.14
日期显示转换为数字
一元运算符+ 的另一个常见的用途是将日期对象(Date)对象强制转换为数字。
var timestamp = +new Date();
显式解析数字字符串
解析字符串中的数字和将字符串强制类型转换为数字的返回结果都是数字。
例如:
var a = "42";
var b = "42px";
Number(a); // 42
parseInt(a); // 42
Number(b); // NaN
parseInt(b); // 42
解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。
parseInt(..) 针对的是字符串,像parseInt(..) 传递数字和其他类型的参数是没用的
显示转换为布尔值
ToBoolean 是显式的ToBoolean 强制类型转换:
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
Boolean(a); // true
Boolean(b); // true
Boolean(c); // true
Boolea(d); // false
Boolea(e); // false
Boolea(f); // false
Boolea(g); // false
一元运算符!显示地将值强制类型转换为布尔值。
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
!!a; // true
!!b; // true
!!c; // true
!!d; // false
!!e; // false
!!f; // false
!!g; // false
隐式强制类型转换
隐式地简化
字符串和数字之间的隐式强制类型转换
+运算符既能用于数字加法,也能用于字符串拼接。
var a = "42";
var b = "0";
var c= 42;
var d = 0;
a + b; // "42"
c + d; // 42
对象的 - 操作与 + 类似;
var a = [3];
var b = [1];
a - b ; // 2
布尔值到数字的隐式强制类型转换
隐式强制类型转换为布尔值
下面的情况会发生隐式强制类型转换
1.if(..) 语句中的条件判断表达式。
2.for(..;...;..)语句中的条件判断表达式(第二个)
3.while(..) 和do..while(..) 循环中的条件判断表达式。
4.? : 中的条件表达式
5.逻辑运算符 || (逻辑或) 和 (逻辑与) 左边的操作数(作为条件判断表达式)
|| 和 &&
|| 和 && 运算符 的返回值并不一定是布尔类型,而是两个操作数其中的一个的值
var a = 42;
var b = "abc";
var c = null;
a || b; // 42
a && b; // "abc"
c || b; // "abc"
c&& b; // null
对于 || 来说 如果条件判断结果为true 就返回第一个数的值,如果为false 就返回第二个操作数。
&& 则相反。
下面是一个|| 十分常见的 || 用法。
function foo(a,b){
a = a || "hello";
b = b || "world";
console.log(a + " " + b );
}
foo(); // "hello world"
foo("yeah","yeah"); // "yeah yeah"
符号的强制类型转换
宽松相等和严格相等
“== 允许在相等比较中进行强制类型转换, 而=== 不允许”
抽象相等
有几个非常规的需要注意
NaN 不等于NaN
+0 等于-0
宽松不相等 != 就是==的相反, !== 同理
字符串和数字之间的相等比较
1.如果Type(x) 是数字,Type(y)是字符串,则返回 x== ToNumber(y)
的结果。
2.如果Type(x) 是字符串,Type(y) 是数字,则返回 ToNumber(x)== y 的结果。
其他类型和布尔类型之间的相等比较
== 最容易出错的地方就是true 和 false 与其他类型之间的相等比较
var a = "42";
var b = true;
a == b; // false
1.如果Type(x) 是布尔类型,则返回ToNumber(x) == y 的结果
2.如果Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果
首先:
var x = true;
var y = "42";
x == y; // false
反过来
var x = "42";
var y = false;
x == y; // false
null 和undefined 之间的相等比较
null 和undefinded 之间的 == 也涉及隐士强制类型转换。
1.如果 x 为 null ,y 为 undefined ,则结果为 true
2.如果x 为undefined, y 为 null, 则结果为 true
var a == null;
var b;
a == b; // true
a == null; // true
b == null; // true
a == false; // false
b == false; // false
a == "" ; // false
b == ""; // false
a == 0; // false
b == 0; // false
对象和非对象之间的相等比较
关于对象和(对象/函数/ 数组) 和标量基本类型(字符串/数字/布尔值)之间的比较。
1.如果Type(x) 是字符串或数字,type(y)是对象,则返回 x == ToPrimitive(y) 的结果
2.如果Type(x) 是对象, Type(y)是字符串或数字,则返回
ToPromitive(x) == y 的结果。
var a = 42;
var b = [42];
a == b; // true
var a = "abc";
var b = Object(a); // new String(a) 一样
a === b; // false
a == b; // true
a == b 结果为true,应为b 通过ToPromitive 进行强制类型转换,并返回基本类型值 “abc”,与 a 相等。
假值相等的比较
一下是常规和非常规的比较
"0" == null; // false
"0" == undefined; // false
"0" == false; // true -- 晕!
“0” == NaN; // false
"0" == 0; // true
"0" == ""; // false
false == null; // false
false == undefined; // false
false == NaN; // false
false == 0; // true -- 晕!
false == "" // true -- 晕!
false == [] // true -- 晕!
false == {} // false
"" == null; // false
"" == undefined; // false
"" == NaN; // false
"" == 0; // true -- 晕!
"" == []; // true -- 晕!
"" == {}; // false
0 == null; // false
0 == undefined; // false
0 == NaN; // false
0 == []; true -- 晕!
0 == {}; false
因为他们属于假阳。
极端情况
[] == ![] // true
对布尔值进行强制类型转换 [] == ![] 变成 [] == false,
2 == [2]
"" == [null]; //true
42 == "43" // false
"foo" == 42; // false
"true" = '"" // false
42 == "42" // true
"foo" == ["foo"] // true
安全运用隐式强制类型转换
1.如果两边的值中有true 或者 false, 千万不要使用 ==.
2.如果两边的之中有[],"" 或者 0 ,尽量千万不要使用==.这时候最好使用 === 来避免强制类型的转换。
抽象关系比较
双方都是字符串比较
var a = ["42"];
var b = ["043"];
a < b; // false
a 和b 并没有被准换为数字,因为ToPrimitive 返回的是字符串,
比较的是 "42 " 和 "043" 两个字符串, 因为"0"在字母顺序上小于
“4”,所以最后结果为 false.
同理
var a = [4,2];
var b = [0,4,3];
a < b; // false
a 被转为 “4,2”,b 转为 “0,4,3” 同样式按字母顺序进行比较的。
var a = {b: 42};
var b = {b:43};
a < b ; // false
a 是 [object Object], b也是 [object Object] 所以按着字母顺序
a < b 不成立。
下面的例子
var a = {b: 42};
var b = {b:43};
a < b; // false
a == b; // false
a > b; // false
a <= b; // true
a >= b; // true