primers

To acquire a deep object, for everyone is a routine thing. Like their own package, third-party libraries and ES2020 to provide, in short, share and discuss

Get the city address of the user

const user = {

 name'xxx'.

 address: {

  city'hangzhou'

 }

};

Copy the code

The most direct

const ctiy = user && user.address && user.address.city;

// or

constcity = ! user ?undefined : !user.address ? undefined : user.address.city;

Copy the code

Every time I add a line to the object, I need another layer to determine whether I can write a parsed function to get the value of user.name.address.city if I know the path

Manual implementation

var user = {

 name'xxx'.

 address: {

  city'hangzhou'

 }

};

const str = 'address.city';

const get = (obj, path, defaultValue) => {

 let result = obj, i = 0;

 const paths = path.split('. ');

 while (i < paths.length) {

        result = Object(result)[paths[i]];

  if (result === undefined) {

   return defaultValue;

        }

        i++

 }

 return result;

};

console.log(get(user, str), '--');

// hangzhou

Copy the code

So we’re actually going to add, and it’s going to be easy to add one line to each of the array subscripts

Optimized version

var user = {

 name'xxx'.

 address: {

  cities: [{city'hangzhou'}]

 }

};

const str = 'address.cities[0].city';

const get = (obj, path, defaultValue) => {

    let result = obj, i = 0;

    // Add this line ————————————————————————————

    const paths = path.replace(/\[(\d+)\]/g.'$1').split('. ')

    console.log(paths, The '-')

 while (i < paths.length) {

  result = Object(result)[paths[i]];

  if (result === undefined) {

   return defaultValue;

  }

  i++;

 }

 return result;

};

console.log(get(user, str), '--');

/ / hangzhou

Copy the code

Big guy one line version

var mb=p=>o=>p.map(c=>o=(o||{})[c])&&o

There’s a guy who wrote a mb.js line that implements get as an array

var getHello = mb(["a"."b".0."hello"]);

var getHelloLength = mb(["a"."b".0."hello"."length"]);



var obj1 = {

  a: {

    b: [{ hello"world" }]

  }

};

var obj2 = {

  c: {

    d"e"

  }

};

getHello(obj1); // world

getHelloLength(obj1); / / 5



getHello(obj2); // undefined

getHelloLength(obj2); // undefined

Copy the code

All of the above operations can be implemented if you define your own parser

lodash/get

const city  = get(user, 'address.cities[0].city'))

Copy the code

Let’s take a look at the source./get.js

import baseGet from './.internal/baseGet.js'

function get(object, path, defaultValue{

  // the procedure is simple. DefaultValue is the defaultValue of undefined. All values are in the 'baseGet' module.

  const result = object == null ? undefined : baseGet(object, path)

  return result === undefined ? defaultValue : result

}



export default get

Copy the code

See baseGet. Js

import castPath from './castPath.js'

import toKey from './toKey.js'

function baseGet(object, path{

  // All paths are converted to arrays

  path = castPath(path, object)

  let index = 0

  const length = path.length

  while(object ! =null && index < length) {

    // The key is changed to a unique key

    object = object[toKey(path[index++])]

  }

  // Check the key array

  return (index && index == length) ? object : undefined

}

export default baseGet

/ * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /

// Split castpath.js

import isKey from './isKey.js'

import stringToPath from './stringToPath.js'

function castPath(value, object{

  if (Array.isArray(value)) {

    return value

  }

  // Convert to a key array

  return isKey(value, object) ? [value] : stringToPath(value)

}

export default castPath

// isKey.js

function isKey(value, object{

  if (isArray(value)) { // Array, return false

    return false;

  }

  if (type == 'number' || type == 'symbol' || type == 'boolean' ||

      value == null || isSymbol(value)) {

    return true;

  }

  returnreIsPlainProp.test(value) || ! reIsDeepProp.test(value) ||

(object ! =null && value in Object(object));

}

Copy the code

IsKey (value, object) is used to determine whether a value is the key of an object, like object[value]

Ramda

Ramda is a one-two punch. After all, Ramda is a functional programming library. Let’s take a look at the implementation

// The one-step version, which has no default option

const city = R.path(['address'.'cities'.0.'city'])(user)

// Version with default parameters

R.pathOr([], ['user'.'posts'.0.'comments'])

/ /

const city = R.compose(

    R.prop('city'),

    R.path(['address, cities'.0,])(user)

Copy the code

Kind of the way

const user = {

    address: {

        city'hangzhou'

    }

}

class GetValue {

 constructor(val) {

  this.__val = val;

 }

 static set(val) {

  return new GetValue(val);

 }

 isNothing() {

  return this.__val === null || this.__val === undefined;

 }

 map(f) {

  return this.isNothing() ? new GetValue(null) : new GetValue(f(this.__val));

 }

}

const prop = key= > obj= > obj[key]

const city = GetValue.set(user).map(prop('address')).map(prop('city'))

console.log(city, 'city')

// GetValue { __val: 'hangzhou' } city

Copy the code

We’ve been doing this for so long, but ES2020 has already provided a new way to do it for us

Optional Chaining operators

Optional chain we do not need to nullate in various ways when querying multi-layer objects

constcity = address? .cities[0]? .city

Copy the code

When the left is empty, the right value is taken, otherwise the left value is taken. Null refers to null and undefined, which is different from false values and the difference between using null operators and logical or operators

compatibility


precondition

  • Nodejs v > = 14.0.0
  • The TypeScript v > = 3.7
  • Babel plug-in support
// install

yarn add @babel/plugin-proposal-optional-chaining

 --dev / / optional link chain

yarn add @babel/plugin-proposal-nullish-coalescing-operato --save / / double question mark

 // use

 {

"plugins": ["@ Babel/plugin - proposal - optional - chaining"].

"@babel/plugin-proposal-nullish-coalescing-operator"

}

Copy the code
  • The framework does not primarily support vue templates

More 🌰

Dynamic key

 const obj = { a: { b'b'}}

 const name = 'b'

 constb = obj? .a? .[name]

Copy the code

Three yuan

const city = user ? user.name : 'xxx' / / before

constcity = user ? .name ??'xxx' / / after

Copy the code

After I use it, my code becomes a question mark

The last

Although we have been working on this for so long, we are probably only writing crawler scenes with relatively deep objects. If you come across such a deep data structure from the back end of your work, you should spray it, do not use these useless