javascript 资料型態/结构验证库 : Skeletons

栏目: JavaScript · 发布时间: 7年前

内容简介:当初专案需要将资料以JSON格式储存在本地端,万一资料结构出了问题或是不符合预其,后面程式都会出问题,因此想写一个简单直觉的纯JS资料验证方法,并开源到npm上。希望对大家有帮助。喜欢可以给个星:) 有任何讨论都欢迎。先来介绍一下Javascript有趣的资料型态,如有错误请帮忙提出修正~

当初专案需要将资料以JSON格式储存在本地端,万一资料结构出了问题或是不符合预其,后面程式都会出问题,因此想写一个简单直觉的纯JS资料验证方法,并开源到npm上。

希望对大家有帮助。喜欢可以给个星:) 有任何讨论都欢迎。

源码

Javascript 型态

先来介绍一下Javascript有趣的资料型态,如有错误请帮忙提出修正~

JS 共有七种资料型态

其中包含六种 Primitive types :

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol

和 Object

特别的是 Function 广义来说也是属于物件。

我们可以用 typeof 来检查型态 (回传一个字串)

typeof 1 // 'number'
typeof "" // 'string'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof null // 'object'
typeof Symbol // 'symbol'
typeof function(){ } // 'function'
typeof {} // 'object'
复制代码

等等,你有没有发现什麽端倪?我们一个一个看。

Number

一般我们会直接定义变数:

let a = 1
复制代码

也可以用 function 定义

let a = Number(1)
typeof a // 'number'
复制代码

但如果加上 new ,则会创建一个Number 物件

let a = new Number(1)
typeof a // 'object'
复制代码

NaN 也是属于Number

typeof NaN // 'number'
复制代码

如果要判断变数 a 是可计算的数字且不是 NaN ,以下是行不通的

if(typeof a==='number' && a!==NaN) //... a !== NaN 永远是 true
复制代码

因为 NaN 很特别,它不会等于任何值

// 以下通通都是 false !
NaN == 0 
NaN == false
NaN == NaN
NaN === NaN
复制代码

你可能会想到用 boolean 来判断 true / false

if(typeof a==='number' && !a) // ...
复制代码

但是别忘了还有个 0 :

if(typeof a==='number' && !a && a !== 0) // ...
复制代码

当然最简单的是用 isNaN 这个方法区分

if(typeof a==='number' && !isNaN(a)) // ...
复制代码

Boolean, String

和 Number 很像,注意用new的话会一样是创建object。

let a = true  // boolean
a = Boolean(true) //boolean
a = new Boolean(true) //object
复制代码

Undefined

也是一种premitive type

undefinednull 是没有 funtion的 ,直接指定值就好

typeof undefined // 'undefined'
复制代码

值得一提的是,虽然以下都是否定值 (false)

Boolean(0)
Boolean(false)
Boolean('')
Boolean(undefined)
Boolean(null)
复制代码

但动态型别方面 0, false, '' 是一伙的, undefined, null 则是另外一个团体

0 == false  // true
0 == ''     // true
false == '' // true

undefined == null // true

undefined == false // false
undefined == 0 //false
null == '' //false
复制代码

Null

null也是一种type,但是。。。

typeof null // 'object'
复制代码

没错, typeof 打印出来的是 'object'

上网查了一下,有些人说是JS当初设计的错误。

我们要判断一个变数是物件的话可以这样:

if(typeof a === 'object' && a!==null) // ...
复制代码

Symbol

最后一个 premitive type symbol

创建一个 symbol:

let a = Symbol()
typeof a // 'symbol'
复制代码

注意不能用 new ,会丢出错误

let a = new Symbol()
> Uncaught TypeError: Symbol is not a constructor
复制代码

Object

除了上面六种 primitive type,其他都归类为物件

但特别的是 function ,使用 typeof 检查会回传 function 字串:

typeof function(){} // 'function'
复制代码

让我们能很好的区别 function 和其他一般的物件

Skeletons

接下来要介绍这个库了,有兴趣的话可以先看看 介绍

请先记好上面 Javascript 原生定义的资料型别,因为这个库的分类有些不一样

Skeletons 中可定义的类型除了原本的七种JS类型,额外分出 array 和 function

原因是这两个都是很常用的,将他们从物件特别区分出来。

使用方法

定义一个规则,使用 validate 来验证资料

const rule = new Skeletons(schema)
rule.validate(data)
复制代码

Schema

定义规则需要传入一个 schema ,也就是你设想的资料结构以及形态

schema 可以有四种

1. premitive type function

共有四种可以用 (undefined和null是没有function的,我们后面谈如何定义)

  • Number
  • Boolean
  • String
  • Symbol

分别定义四种形态,使用上不用呼叫,直接传入function

如下,定义一个型态为数字的schema

const schema = Number
复制代码

2. 使用 object literal

使用最值觉的 object literal 来定义一个物件 (注意,在Skeletons会排除array和function)的key

每个key都可指派另一个schema

如下定义了一个有 x, y 两个键的物件,且两个键的值都是数字型态

const schema = {
  x: Number,
  y: Number
}
复制代码

使用这种方式,让你能够轻易地定义结构较深的物件

const userSchema = {
  name: String,
  id: String,
  VIP: {
    code: Number,
    details: {
      type: String,
      level: Number,
      expired: Boolean
    }
  },
}
复制代码

3. array literal

使用array literal来定义有固定元素數量的array

const schema = [String, Number, Skeletons.Function()]
复制代码

4.呼叫Skeletons的静态方法

  • Skeletons.Number()
  • Skeletons.String()
  • Skeletons.Boolean()
  • Skeletons.Null()
  • Skeletons.Symbol()
  • Skeletons.Any()
  • Skeletons.Array()
  • Skeletons.Object()
  • Skeletons.Function()
  • Skeletons.MapObject()

共有十种方法,分别代表是五种premitive type (不含undefined)、Object, 从物件中分出来的 Array, Function,以及特殊的Any(任何非undefined的型态) 和 MapObject

每种方法都接受一个 options 物件当做参数,

且都可定义三个基本的property

  • options.required

    type: Boolean

    default: true

    Skeletons对于任何 undefined 值都会认定为验证失败:

    new Skeletons({
      a: Number
    }).validate({})
    // data.a got undefined, validation filed
    复制代码

    如果要允许该层资料可以为 undefined ,设 options.required 为 false

    new Skeletons({
      a: Skeletons.Number({
        required: false
      })
    })
    复制代码
  • options.default

    type: 任何

    default: undefined

    有时后资料的预设值(或者空值)的型态可能会和资料有值的时后不一样,比方说有人可能会用 null 来替代空的物件。

    new Skeletons(Skeletons.Object({
      default: null
    }))
    复制代码
  • options.validator

    type: Function

    传入一个function,回传 true / false 来验证资料

    validator(value, data)
    复制代码

    该函数可接收两个参数: value 代表该层资料的值, data 代表整个资料

    以下这个例子, value 等于 120 , data 等于整个 datasource

    const datasource = {
      a: 120,
      b: 240
    }
    
    new Skeletons({
      a: Skeletons.Number({
        validator: (val, data) => {
         // in this case, val = 120, data = datasource
         return val === data.b*2
        }
      }),
      b: Number
    })
    复制代码

更多详细的介绍可以参考 文件

验证

验证可分为

  • 使用 console 打印出错误资讯
  • 直接抛出错误

如何设定可参考 文件

每次验证后,可由 warnings 属性获得错误资讯

const rule = new Skeletons(Number)
rule.validate('1')
rule.warnings // 一串array 包含所有错误资讯
复制代码

关于错误资讯可参考 warnings

示例

接下来演示一些资料定义的范例

范例一 : 阵列

定义一个 schema 代表不是 NaNnumber

// ex: 1
const calcNum = Skeletons.Number({
  allowNaN: false
})
复制代码

定义一个 array ,每个元素是含有 x , y 属性,值为非 NaN 数字的物件

// ex: [{x: 1, y: 2}, {x: 3, y: 5}]
new Skeletons(
  Skeletons.Array({
    item: {
      x: calcNum,
      y: calcNum
    }
  })
)
复制代码

规定 array 一定要有元素

// ex: [{x: 1, y: 2}, {x: 3, y: 5}]
new Skeletons(
  Skeletons.Array({
    validator: ary=>ary.length>0,
    item: {
      x: calcNum,
      y: calcNum
    }
  })
)
复制代码

范例二 : 和其他资料比对

假设有一笔资料,当 age 大于 18, grownup 等于 true 代表已成年,反之则为 false

const ex = {
  age: 19,
  grownup: true
}
复制代码

我们可以用 validator 来进行检查

new Skeletons(
  {
    age: Number,
    grownup: Skeletons.Boolean({
      validator: (val, data) => val === data.age>=18
    })
  }
).validate(ex)
复制代码

范例三: 不限制物件的key

有时后物件作为一个类似map来除存对应的key,代表并没有固定的属性值和数量。这时可以使用 MapObject

例如 room 以房间的id当做key来mapping

const room = {
  idkfd: {
    name : 'have fun',
    members: 4,
    id: 'idkfd'
  },
  ckclo: {
    name : 'My room',
    members: 2,
    id: 'ckclo'
  }, 
  ppqkd: {
    name : 'User0001\'s room',
    members: 8,
    id: 'ppqkd'
  } 
}
复制代码

可这样定义

new Skeletons(
  Skeletons.MapObject({
    keyValidator: (k, data)=> k === data[k].id,
    item: {
      name: String,
      members: Number,
      id: String
    }
  })
)
复制代码

以上所述就是小编给大家介绍的《javascript 资料型態/结构验证库 : Skeletons》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Music Recommendation and Discovery

Music Recommendation and Discovery

Òscar Celma / Springer / 2010-9-7 / USD 49.95

With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具