JavaScript:undefined!=false之解 及==比较的规则

js的一些概念:undefined,null,0,false 的布尔值 均是 false

JS中有一个基本概念就是: 
JavaScript中undefined==null 
但undefined!==null 
undefined与null转换成布尔值都是false 
如果按照常规想法,比如下面的代码

Js代码

var a=1;   
alert(Boolean(a));//返回true   
//那么下面的代码也应该返回true   
alert(1==true);   
  
//但肯定的,下面的代码会返回false   
alert(1===true);  

但对于下面的代码,估计会让大部分JS程序员疑惑

Js代码

alert(123==true);//为什么返回false   
  
  
alert(Boolean(undefined));//outputs false   
alert(Boolean(null));//outputs false   
  
alert(undefined==false);//竟然返回false   
alert(null==false);//竟然也返回false  


至于其原因,下面作一个尝试性的解析(是尝试性的解析) 

首先看看JS中的==比较是如何比较的 
对于标量,“==”直接比较其中的值就行了 
而对于两个对象(这里特指除去原始值的对象……因为在JS可以说一切皆对象) 
则是比较其引用 
因此对于两个对象的比较,看它们是不是同一个对象,是不需要用===(严格相等,值相等且类型相同)的 


再深入分析下JS对于标量应用==比较时的情况 
对于相同类型的两个标量的比较,除了NaN比较特殊之外(NaN==NaN返回false),都没什么疑点 
而对于类型不同的两个标量的比较,JS就有一套严格的规则,这规则JS解析引擎具体怎样执行的,抱歉,还没去看JS解析引擎的源代码呢,这里只好对其表现作个总结 
1.将Boolean,Number,String这三种类型进行不同类型的==比较时,其规则是,总将两边的值转换成数字,再看看转换结果数字是否相等 
如下代码

Js代码 

alert(1==true);//true转换成数字也是1   
alert('1'==true);//将字符串'1'与true都转换成数字   
  
alert('abc'==true);//虽然字符串'abc'转换成布尔值是true,但这里会返回false   
//因为'abc'转换成数字是NaN,而true转换成数字是1   
  
alert(123=='123');//同理,true  

而undefined与null,它们是简单类型还是引用类型呢? 
将上面的规则 应用于undefined与null时就不正确了,在解析之前,先看看==比较的其它形式 

JS中简单类型与引用类型进行==比较的情况 
这种比较与是有规则的,并且可以用代码来验证JS内部的执行情况 
将一个简单类型(这里指除undefined与null的值)与一个对象比较时, 
先调用对象的valueOf方法,以期待返回一个标量,如果对象的valueOf方法返回的仍然是一个复合对象的话 
就接着调用对象的toString方法以期待返回一个标量,如果仍然没有返回标量的话,就判为不相等 
如果valueOf或toString方法之一返回一个标量,就用这个标量同==另一边的标量进行比较

Js代码 

var obj={};   
alert(obj=="abc");//false   
obj.toString=function () {   
    return 'abc';   
};   
alert(obj=='abc');//这时就返回true了   
  
alert(obj==123);//false   
obj.valueOf=function () {return 123};   
alert(obj==123);//true!!!   
  
obj.valueOf=undefined;//先将这个方法清空掉,以免受上面的代码影响   
alert(obj==true);//false   
obj.valueOf=function () {   
  return 1;//只要返回一个能转换成布尔值的标量就行了,1或true都行,都表示true   
};   
alert(obj==true);//true!!!!  


事实上还可以用下面的代码进行验证,将一个复合对象与标量进行比较时,总会先调用对象的valueOf, 
valueOf方法返回不是一个标量的话还会接着调用toString方法

Js代码 

var obj={   
    toString:function () {   
        alert('valueOf方法没有返回标量,我会被调用');   
    },   
    valueOf:function () {   
        alert('我先被调用,Object的valueOf方法默认实现是返回对象自身');   
    }   
};   
alert(1==obj);//可以看到执行次序  

那么讲了这么多,这和undefined!=false有什么关系呢? 
JS中的==对两边的对象进行比较时,undefined将被转换成数字,也就是说,undefined被看成基本值 
而又由于undefined转换成数字为NaN,所以将Number,String,Boolean这三种类型与undefined比较时,总是返回false 
而对于null,JS则将其当成对象来比较,即尝试调用null的valueOf与toString方法,再将返回的结果与另一个值进行比较,可以推断null==false返回false的原因是因为null的valueOf实现导致的 
由于null没有valueOf与toString方法,因此始终返回false 

valueOf() 方法可返回 Boolean 对象的原始值。booleanObject 的原始布尔值。

toString() 方法可把一个逻辑值转换为字符串,并返回结果。根据原始布尔值或者 booleanObject 对象的值返回字符串 "true" 或 "false"。
ECMAScript规范是怎么说的? 
ECMAScript规范中指出,a与b进行比较,如果a与b是Number,String,Boolean这三种类型中的一种, 
并且a与b的类型不同,那么就将a与b都转换成数字再进行比较 
也就是说

Js代码 

var a="true";   
var b=true;   
alert(a==b);   
//结果等同于下面的代码   
alert(Number(a)===Number(b));  


而如果a是Number,String,Boolean这三种类型中的一种,而b是一个复合对象时(Object,Array等) 
则对b执行ToPrimitive操作(这步是JS解释器执行的) 

Js代码 

var a="abc";   
var b={};   
alert(a==b);   
//上面的一行代码在JS解析时将被解释成   
//a==ToPrimitive(b);  

而这个ToPrimitive方法的实现,正是依次去调用对象的valueOf,toString方法,直到其中一个方法返回一个基本值 
如果这两个方法没有返回基本值 ,那就认定不相等 

而当a和b都是复合对象时,就很简单,就看a和b是不是同一个对象的引用! 

而对于将undefined,null与其它类型进行比较的,则没具体说,只说了将 
任何基本类型与Boolean类型比较时,会将其转换成数字(与前面的规则一样) 

总结 
Number,Boolean,String,Undefined这几种基本类型混合比较时,会将其转换成数字再进行比较 
基本类型与复合对象进行比较时,会先将复合对象转换成基本类型(依次调用valueOf与toString方法)再进行比较 
undefined被当成基本类型,undefined转换成数字是NaN,因此undefined与除null之外的其它类型值进行比较时始终返回false(注意NaN==NaN返回false) 
null被当成复合对象,由于null没有valueOf与toString方法,因此和除了undefined之外的其它类型值进行比较时始终返回false 

原文地址:https://blog.csdn.net/wangfengqingyang/article/details/39519609

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以在 `fromDataRules` 中添加一个自定义规则来实现该功能,代码如下: ```javascript fromDataRules: { controlok: [ { required: true, message: '请输入', trigger: 'blur', validator: (rule, value, callback) => { let index = rule.field.split('.')[1]; let row = this.list[index]; if (row.iscontrol === true && (value === undefined || value.trim() === '')) { callback(new Error('请输入')); } else { callback(); } } } ] } ``` 在该规则中,我们定义了一个自定义验证函数 `validator`,它会在输入框失去焦点时被调用。该函数会根据当前行的 `iscontrol` 值和 `controlok` 的值来判断是否需要进行验证。如果需要验证且 `controlok` 值为空,则会调用 `callback(new Error('请输入'))` 来提示用户输入。否则,调用 `callback()` 来表示验证通过。 在模板中,我们需要绑定 `fromDataRules.controlok` 规则,在 `el-form-item` 组件中添加 `prop` 属性,并将其值设为 `'list.' + scope.$index + '.controlok'`,这样该规则就会应用到该行的 `controlok` 属性上。 ```html <template slot-scope="scope"> <el-form-item :prop="'list.' + scope.$index + '.controlok'" :rules="fromDataRules.controlok"> <el-input v-if="scope.row.controluse === 'S2F21'" :disabled="scope.row.iscontrol === false || scope.row.iscontrol == null || scope.row.iscontrol == ''" v-model="scope.row.controlok" filterable clearable /> <el-select v-else v-model="scope.row.controlok" :disabled="scope.row.iscontrol === false || scope.row.iscontrol == null || scope.row.iscontrol == ''" :placeholder="t('web_ems_tip_pleaseInput')" filterable clearable> <el-option v-for="item in identifyingList" :key="item.id" :label="item" :value="item" /> </el-select> </el-form-item> </template> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值