js 你不知道的那些东西(贰)——判断对象中是否存在某个属性

137 阅读3分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

定义一个函数,传入一个对象,一个属性名,怎么样判断这个对象中是否存在这个属性呢?

这篇文章会详细讲解怎么样来解答这道题,并且纠正一些误区

     /**
     * 判断对象中是否存在某个属性。
     * @param {Object} Obj 对象
     * @param {String} Key 属性名
     */
    function MyProperty (Obj, Key) {

    }

一些常见写法:

1、

    function MyProperty (Obj, Key) {
      return Key in Obj
    }

这样写其实是正确的,但你知道什么吗?

2、

    function MyProperty (Obj, Key) {
      return Obj[Key] !== undefined
    }

那为什么这样写也不对呢?

比如Obj里卖弄有一个属性a,a的值正好是undefined

    function MyProperty (Obj, Key) {
      return Obj[Key] !== undefined 
    }
    var Obj = { a: undefined }
    console.log(MyProperty(Obj, 'a'));

按道理应该会返回true,但其实是false。

image.png

所以我们并不能用undefined来判断,那应该如何判断呢?

3、

   function MyProperty (Obj, Key) {
      return Object.keys(Obj).includes(Key)
    }
    var Obj = { a: undefined }
    console.log(MyProperty(Obj, 'a'));

这样写就会返回一个true

image.png

为什么呢?

 Object.keys(Obj)

其实这个表达式可以得到对象里面的所有属性,并形成一个数组。

 console.log(Object.keys(Obj));

image.png

然后会调用数组的includes方法来判断属性是否存在。好像没有什么问题,但是

如果这样写就不行了:

    var Obj = { a: undefined }
    Object.defineProperty(Obj, 'c', {
      enumerable: false,//不可以遍历
      value: 1
    })
    // 打印一下
    console.log(Obj.c);

确实可以拿到:

image.png

但是:

   function MyProperty (Obj, Key) {
      return Object.keys(Obj).includes(Key)
    }
    var Obj = { a: undefined }
    Object.defineProperty(Obj, 'c', {
      enumerable: false,//不可以遍历
      value: 1
    })
    console.log(MyProperty(Obj, 'c'));

image.png

返回的却是一个false,也就是说:Object.keys(Obj)是拿不到这个属性c的

 console.log(Object.keys(Obj));

image.png

4、

   function MyProperty (Obj, Key) {
      return Obj.hasOwnProperty(Key)
    }
    var Obj = { a: undefined }
    Object.defineProperty(Obj, 'c', {
      enumerable: false,//不可以遍历
      value: 1
    })
    console.log(MyProperty(Obj, 'c'));

hasOwnProperty这个函数是js专门用来判断某一个对象里面是否存在一个属性。但是会存在一个误区,假如:

    function MyProperty (Obj, Key) {
     return Obj.hasOwnProperty(Key)
    }
    var Obj = { a: undefined }
    Object.defineProperty(Obj, 'c', {
      enumerable: false,//不可以遍历
      value: 1
    })
    console.log(MyProperty(Obj, 'toString'));

很显然Obj里面没有一个叫toString的属性

    console.log(Obj.toString);

但是输出结果会让你大吃一惊,

image.png

结果显示确实有toString这个东西,并且是个函数,那toString是哪来的呢?

其实是在原型链上,对象中没有的属性,js会在原型链上找 看有没有这个。

但是hasOwnProperty这个函数并不能判断出来所以这么写也是不严谨的。

所以正确的写法应该是第一个,

    /**
     * 判断对象中是否存在某个属性。
     * @param {Object} Obj 对象
     * @param {String} Key 属性名
     */
    function MyProperty (Obj, Key) {
      return Key in Obj
    }
    var Obj = { a: undefined }
    Object.defineProperty(Obj, 'c', {
      enumerable: false,//不可以遍历
      value: 1
    })
    console.log(MyProperty(Obj, 'c'));
    console.log(Obj.toString);

image.png

in关键字可以判断对象里面是否存在某一个属性,并且in关键字可以在原型链上被找到。
往往越简单的东西,越复杂。

往期文章

最后

我是小晨,一个不想加班的加班族