1. 原始数据遇运算符
1. +运算符
1) 如果算子两侧都是字符串,返回拼接结果;
2) 如果算子两侧不全是字符串,则根据实际情况:
- 如果需要字符串,就调用String();
true + "1"; // "true1"
- 如果需要数字转为数字,就调用Number();
true + 1; //2
- 如果都可以,优先转为数字。
true + true; //2
2. -*/减法、乘法、除法运算符
所有的算子全部转为数字,使用Number()/+。
'4' - '5'; // -1 4-'5'; //-1 true - false; // 1 '4'/'5'; 0.8
3.非相等比较运算符
>,>=,<,<=
1)如果算子两侧都是字符串,按照Unicode码点依次比较大小
2)如果算子两侧不全是字符串,转为数字进行比较(Number()/+)。
true < '8'; // true '7' < 8; // true
4.相等比较运算符(==)
1) 如果是不同原始类型的值,将字符串和布尔值都转为数字(Number()或者+)。
true == '1'; //true 'true' == true; // false Number('true')->NaN // NaN用于任何运算符返回值都是false
2)如果其中一方是对象,先将其转为原始类型的值
如果两侧都是对象,则永远不相等。
3) null == undefined
4)null和undefined都不等于其他值
null == 0; //false undefined == 0; //false
4) NaN 和任何值都不相等
5.严格相等运算符(===)
1)如果类型不相同,直接返回false
2)如果类型相等,值也相同,直接返回true
2. 对象遇到运算符
1.+运算符
最终结果是对象需要转化成原始数据。
1)对象首先调用valueOf()方法,如果不自定义,一般都返回自身;
2)再调用toString()方法,返回对应的字符串。
但是,Date对象不同,是先调用toString(), 后调用valueOf()
var arr = [5]; arr + 1;// "51" var obj = { toString() { return "hello"}, valueOf() {return 1} }; obj + "2"; // "12" 不管另一个算子是什么类型,都是先调用valueOf() var date = new Date(); date.toString = function(){return "hello"}; date.valueOf = function(){return 1}; date + 1; // "hello1" 不管另一个算子什么类型,都是先调用toString()
2. -*/减法、乘法、除法运算符
和直接调用Number()一样;
Date对象和其他对象一样,遵循Number()函数的调用规则;
var obj = { valueOf(){return "8"}, toString() {return "9"} } obj - 8; // 0 var date = new Date(); date.valueOf = function(){return "8"}; date.toString = function(){return "9"}; date - 8; // 0
3.非相等比较运算符
规则和+运算符(Number()工具函数)一致。
1)先调用valueOf()方法,如果返回值不是原始值,再调用toString()方法
2)调用toString()后还不是原始值,返回NaN
Date对象和其他对象一样,遵循上面的规则!
var obj = { valueOf(){return "8"}, toString() {return "9"} } obj > 8; // false var date = new Date(); date.valueOf = function(){return "8"}; date.toString = function(){return "9"}; date > 8; // false
4. 相等运算符(==)
如果运算符两侧都是对象,除非地址相同,否则返回都是false;
如果比较符一侧是原始类型的值:
1)先调用valueOf(),如果返回不是原始类型的值,再调用toString();
2) 如果toString()的值返回的还不是原始类型,返回NaN
Date类型相反,先调用toString();
var obj = { valueOf(){return "8"}, toString() {return "9"} } obj == 8; // true var date = new Date(); date.valueOf = function(){return "8"}; date.toString = function(){return "9"}; date == 8; // false
应用:
若使得下面条件成立,a应该使什么值?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script type="noscript"> a什么情况下,使得下面的条件成立 if(a == 1 && a ==2 && a ==3) { console.log(1); } </script> <script> //有两类解决方案:1)数据拦截 2)类型转换 /** * 1)数据拦截 * a本身可以看作window,使用Object.defineProperty */ var i = 1; Object.defineProperty(window, 'a', { get() { return i++; } }) /** * 2)类型转换 * > 使用==时,如果是对象,会先转成原始类型的值 * 先调用valueOf(),如果是原始类型的值返回; * 否则再调用toString() */ // 1)重写valueOf方法 var a = { index: 1, valueOf() { return this.index++; } } // 2)重写toString方法 var a = { index: 1, toString() { return this.index++; } } /* * > 使用==时,如果是对象,会先转成原始类型的值 * 对象转原型类型本质上是调用的[Symbol.toPrimitive]方法 * 该方法被调用时,会传入一个参数,表示其转为的预期类型 * default/number/string中的一个 */ var a = { index: 1, [Symbol.toPrimitive](hint) { // 预期是number/string都可以 if(hint === 'default') { return this.index++; } } } // 运行 if(a == 1 && a ==2 && a ==3) { console.log(1); } </script> </body> </html>
5. 严格相等运算符(===)
如果比较符两侧都是对象,除非地址相同,否则都是false;
var obj1 = {}; var obj2 = obj1; obj1 === obj2; // true var obj3 = {}; obj1 === obj3; //false
如果比较符一侧是原始值,直接返回false
3. String()工具函数遇对象
转化规律:
1)先调用toString(),如果返回原始类型的值,对这个值使用String()方法,结束;如果是对象,继续执行;
2)调用原对象的valueOf()方法,如果返回的是原始类型的值,对这个值使用String()方法,结束;
3)如果上面的步骤执行完成后还是不是原始值,报错!
var obj = { valueOf(){ return 5; }, toString() { return 'hello'; } }; String(obj); // "hello" // 当执行完都不返回原始值时 var obj = { valueOf: function () { return {};}, toString: function () { return {};} }; String(obj); //Uncaught SyntaxError: Invalid or unexpected token
4. Number()工具函数遇对象
转化规律:
1)先调用valueOf()方法,如果返回原始值,对这个值使用Number()函数,结束;否则继续
2)调用原对象toString()方法,如果返回原始值,对这个值使用Number()函数,结束;
3)如果都不是原始值,报错
var obj = { valueOf(){ return 5; }, toString() { return 'hello'; } }; Number(obj); // 5
// 当执行完都不返回原始值时 var obj = { valueOf: function () { return {};}, toString: function () { return {};} };
Number(obj); //Uncaught SyntaxError: Invalid or unexpected token
5. 当遇到函数时
当遇到函数调用,就会自动调用函数的toString()方法;
所以执行a();会打印两次2
function a() { var obj = function(){ }; obj.valueOf= function(){console.log(1); }, obj.toString = function() {console.log(2);} return obj; // 2 }; a(); // 2