JavaScript lấy tất cả các khóa trong đối tượng lồng nhau

Để kiểm tra sự tồn tại của các đối tượng lồng thuộc tính, bạn nên thực hiện từng bước một để tránh TypeError. Nó sẽ bị ném nếu ít nhất một trong số các thành viên là null hoặc không xác định và bạn cố gắng truy cập một thành viên

Có hai cách để tránh nó. Bạn có thể bắt ngoại lệ hoặc tạo một hàm để kiểm tra sự tồn tại của nhiều cấp độ như thế này

JavaScript lấy tất cả các khóa trong đối tượng lồng nhau
Kiểm tra sự tồn tại của khóa đối tượng javascript lồng nhau

hàm checkNested(obj /*, level1, level2,. levelN*/ ) { let args = Mảng. nguyên mẫu. lát cắt. cuộc gọi (đối số, 1); . chiều dài; . đối tượng. . đối tượng. hasOwnProperty(args[i])) { return false; . { cấp độ 2. { cấp 3. 'cấp 3' } } }; . log(checkNested(test, 'level1', 'level2', 'level3')); . log(checkNested(test, 'level1', 'level2', 'foo'));

Sử dụng các tính năng ES6 có thể làm cho chức năng này ngắn hơn nữa

function checkNested(obj, level, ...rest) {
  if (obj === undefined) return false;
  if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
  return checkNested(obj[level], ...rest)
}

Để có được giá trị thuộc tính lồng nhau và cũng kiểm tra sự tồn tại của nó, hãy sử dụng một lớp lót sau

JavaScript lấy tất cả các khóa trong đối tượng lồng nhau
Nhận giá trị thuộc tính lồng nhau và cũng kiểm tra javascript

hàm getNested(obj,. đối số) { trả lại đối số. giảm ((obj, level) => obj && obj[level], obj) } const test = { level1. { cấp độ 2. { cấp 3. 'cấp 3' } } }; . log(getNested(test, 'level1', 'level2', 'level3')); . log(getNested(test, 'level1', 'level2', 'level3', 'length')); . log(getNested(test, 'level1', 'level2', 'foo')); . nhật ký (getNested (kiểm tra, 'a', 'b'));

Bạn cũng có thể sử dụng toán tử tùy chọn để truy cập các thuộc tính được lồng sâu bằng cách sử dụng mã thông báo ?

const value = obj ? .level1 ? .level2 ? .level3

Nếu bất kỳ cấp độ đã cho nào được truy cập là null hoặc không xác định, biểu thức sẽ chuyển thành không xác định theo mặc định

Toán tử cũng xử lý các cuộc gọi phương thức một cách an toàn

obj ? .level1 ? .method();

Biểu thức trên tạo ra undefined if obj, obj. cấp 1 hoặc obj. cấp độ 1. phương thức là null hoặc không xác định;

Toán tử xâu chuỗi tùy chọn (?. ) là một đề xuất và cho phép đọc giá trị của thuộc tính nằm sâu trong chuỗi các đối tượng được kết nối mà không cần phải xác thực rõ ràng rằng mỗi tham chiếu đều hợp lệ. Các ?. toán tử chức năng cho phép đoản mạch nếu tham chiếu đánh giá là null hoặc không xác định. Khi được sử dụng với lời gọi hàm, nó trả về undefined trong trường hợp hàm không tồn tại

Trong bài đăng trên blog này, chúng ta sẽ tìm hiểu cách tạo kiểu sử dụng TypeScript, hiển thị tất cả các đường dẫn chính của một đối tượng, bao gồm cả các đường dẫn lồng nhau

Tại sao điều đó lại hữu ích?

Bạn đã bao giờ xây dựng hàm TypeScript nhận một thuộc tính cụ thể của một đối tượng, bằng cách chỉ định đối tượng và đường dẫn đến thuộc tính của đối tượng đó chưa?

const person = {
  name: "John",
  age: 30,
  dog:{
    name: "Rex",
  }
}

function get<ObjectType>(object: ObjectType, path: string){
  const keys = path.split('.');
  let result = object;
  for (const key of keys) {
    result = result[key];
  }
  return result;
}

get(person, "dog.name") // Rex

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Chà, rõ ràng điều này hoạt động rất tốt, nhưng bạn không tận dụng hết lợi thế của TypeScript. Bạn có thể dễ dàng mắc lỗi đánh máy trên đối số thứ hai (đường dẫn) và mất một số loại quý giá khi gỡ lỗi này

Làm thế nào TypeScript có thể giúp chúng tôi sau đó?

Thật không may cho chúng tôi, vẫn chưa có loại tiện ích gốc nào có thể cung cấp cho chúng tôi tất cả các đường dẫn chính bên trong một đối tượng lồng nhau. Nhưng nếu đối tượng của bạn chỉ có 1 mức độ sâu, toán tử

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
1 của TypeScript sẽ hoạt động tốt

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bằng cách này, bạn sẽ có một hàm an toàn kiểu thực, chỉ cho phép bạn thêm

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
2,
const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
3 hoặc
const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
4 làm đối số thứ hai

JavaScript lấy tất cả các khóa trong đối tượng lồng nhau

Nếu bạn không hiểu một số kỹ thuật tôi đã trình bày ở trên, hãy ở lại với tôi, vì tôi sẽ giải thích chi tiết hơn dưới đây

Đối tượng có độ sâu hơn 1 cấp

Bây giờ, đối với các đối tượng có nhiều hơn 1 mức độ sâu,

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
1 gần như không đủ như bây giờ bạn có thể đã nhận ra

Trước khi đi vào chi tiết triển khai của TypeScript, hãy thử nghĩ về một thuật toán cho phép chúng ta lấy tất cả các khóa của một đối tượng có N mức độ sâu

  1. Đi qua các phím của đối tượng
  2. Nếu giá trị của khóa không phải là đối tượng thì đó là khóa hợp lệ
  3. Mặt khác, nếu khóa là một đối tượng, hãy nối khóa này và quay lại bước 1

Với thuật toán này và các nguyên tắc lập trình "đơn giản" này, một câu lệnh lặp, điều kiện và đệ quy, điều này dường như không quá khó

Bây giờ, hãy sử dụng thuật toán đó và xây dựng một hàm JS có thể trích xuất tất cả các khóa của tất cả các nút trong bất kỳ đối tượng cụ thể nào

const value = obj ? .level1 ? .level2 ? .level3
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Vì vậy, chúng tôi biết cách thực hiện điều này theo chương trình, mục tiêu bây giờ là thử và áp dụng cùng loại khái niệm với các toán tử và loại tiện ích hiện có của TypeScript để xây dựng một

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
6 sẽ cung cấp cho chúng tôi tất cả các khóa của một đối tượng dưới dạng các loại chữ

Tạo loại tiện ích TypeScript

Loại tiện ích mà chúng tôi sẽ tạo bên dưới, chỉ khả dụng kể từ TypeScript 4. 0 đã được phát hành, vì nó đã giới thiệu các loại chữ

Trong phần này, chúng ta sẽ đi từng bước về cách tạo một loại tiện ích TypeScript có khả năng trích xuất tất cả các khóa bên trong bất kỳ đối tượng cụ thể nào

định nghĩa loại

Bước đầu tiên để tạo tiện ích này rõ ràng là khai báo một loại TypeScript mới và đặt tên cho nó

1- Khai báo kiểu mới

const value = obj ? .level1 ? .level2 ? .level3
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bước tiếp theo, là làm cho loại này trở thành "chung chung", nghĩa là, nó sẽ chấp nhận bất kỳ đối tượng nào mà chúng ta chuyển vào nó.
TypeScript đã nhúng sẵn tính năng chung này và nó cho phép chúng tôi tạo một tiện ích linh hoạt có thể chấp nhận bất kỳ đối tượng nào.

2- Chấp nhận tham số loại chung

const value = obj ? .level1 ? .level2 ? .level3
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bản thân việc thêm tham số loại chung không hạn chế loại bạn có thể chuyển vào tiện ích. Để làm được điều đó, chúng ta cần thêm từ khóa

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
7, để chỉ chấp nhận các loại đối tượng - bất kỳ loại nào tuân theo kiểu dữ liệu cặp "khóa-giá trị"

3- Ràng buộc tham số chung

const value = obj ? .level1 ? .level2 ? .level3
5

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Tuyệt vời, chúng tôi đã xác định chữ ký của loại, bây giờ chúng tôi cần thực hiện "công việc thực sự", nghĩa là thực hiện triển khai

Loại thực hiện

Quay trở lại thuật toán của chúng ta, bước đầu tiên để tạo tiện ích này là "Đi qua các khóa của đối tượng". TypeScript làm cho điều này trở nên dễ dàng với chúng tôi bằng một thứ gọi là Loại được ánh xạ, đây là một cách để duyệt qua các khóa của đối tượng và đặt loại của giá trị dựa trên từng khóa

1- Đi qua các phím của đối tượng

const value = obj ? .level1 ? .level2 ? .level3
6

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bây giờ chúng ta đã có thể duyệt qua tất cả các khóa của đối tượng và sử dụng chúng để truy cập từng giá trị của đối tượng, chúng ta có thể chuyển sang bước thứ 2 của thuật toán. "Nếu giá trị của khóa không phải là đối tượng thì đó là khóa hợp lệ"

Chúng tôi sẽ thực hiện việc kiểm tra đó bằng cách sử dụng TypeScript có điều kiện, hoạt động như sau

const value = obj ? .level1 ? .level2 ? .level3
7

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

2- Kiểm tra xem đó có phải là khóa hợp lệ không

const value = obj ? .level1 ? .level2 ? .level3
8

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Vì vậy, bây giờ chúng tôi có quyền truy cập vào tất cả các khóa cấp đầu tiên của đối tượng, nhưng rõ ràng là chúng tôi vẫn thiếu đường dẫn đến các thuộc tính của cấp độ khác, chẳng hạn như

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
8 và
const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
9

Để đạt được điều đó, chúng ta nên làm theo bước thứ 3 của thuật toán. "Khác, nếu khóa là một đối tượng, hãy ghép khóa này và quay lại bước 1. "

Để đạt được điều đó, chúng ta cần sử dụng các kiểu đệ quy của TypeScript, thực sự hoạt động như bất kỳ ngôn ngữ lập trình nào khác - có một điều kiện gọi cùng một "kiểu" đã gọi điều kiện đó (tính đệ quy) và có một điều kiện dẫn đến một điều kiện thực tế.

3 - Thêm kiểu đệ quy

obj ? .level1 ? .method();
1

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Về cơ bản là vậy, loại tiện ích

const value = obj ? .level1 ? .level2 ? .level3
00 này đã có khả năng trích xuất tất cả các đường dẫn thuộc tính có thể có của một đối tượng với bất kỳ độ sâu nhất định nào, nhưng TypeScript có thể vẫn sẽ la mắng bạn vì đã sử dụng các chuỗi/số không có trong các ký tự, hãy khắc phục

Để chỉ chọn các khóa của một loại cụ thể, chúng ta cần tận dụng các Loại giao lộ, đây chỉ là vấn đề sử dụng toán tử

const value = obj ? .level1 ? .level2 ? .level3
01

4- Chỉ trích xuất các phím chuỗi/số

const person = {
  name: "John",
  age: 30,
  job: "Programmer"
}

function get<ObjectType>(object: ObjectType, 
  path: keyof ObjectType & string){
 ...
}
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình


SortBy mẫu với NestedKeyOf

Bây giờ chúng ta đã hoàn tất việc triển khai loại tiện ích TypeScript của mình, đã đến lúc xem một mẫu đơn giản mà nó sẽ cực kỳ hữu ích trong bất kỳ dự án nào mà bạn có thể đang làm việc 👇

JavaScript lấy tất cả các khóa trong đối tượng lồng nhau

Bằng cách sử dụng tiện ích này trong hàm

const value = obj ? .level1 ? .level2 ? .level3
02, chúng tôi có thể chọn một trong các thuộc tính của đối tượng một cách an toàn và đảm bảo rằng chúng tôi không mắc bất kỳ lỗi chính tả nào và luôn đồng bộ với cấu trúc của đối tượng và những gì chúng tôi đang chuyển qua 🤯

Bản tóm tắt

  1. Tạo một loại chấp nhận một loại chung
  2. Ràng buộc cái chung là một đối tượng
  3. Tạo một đối tượng mới với sự trợ giúp của Mapped Type
  4. Đối với mỗi khóa, hãy kiểm tra xem giá trị là một đối tượng hay kiểu nguyên thủy
  5. Nếu đó là một đối tượng thì hãy nối khóa hiện tại và gọi loại theo cách đệ quy
  6. Chỉ tìm các phím chuỗi và số

Lưu ý thêm, tôi muốn đánh giá cao David Sherret tuyệt vời, người đã đăng một câu trả lời tràn ngăn xếp trông giống như loại tiện ích mà tôi đã mô tả ở trên 🙏

Làm cách nào để lấy khóa của đối tượng lồng nhau trong JavaScript?

Làm cách nào để lấy khóa và giá trị của một đối tượng? .
Sự vật. keys(obj) – trả về tất cả các khóa của đối tượng dưới dạng mảng
Sự vật. giá trị (obj) – trả về tất cả các giá trị của đối tượng dưới dạng mảng
Sự vật. entry(obj) – trả về một mảng [key, value]

Làm cách nào để lấy giá trị từ đối tượng lồng nhau trong JavaScript?

Nhận giá trị lồng nhau trong đối tượng dựa trên mảng khóa .
So sánh các khóa bạn muốn trong đối tượng JSON lồng nhau dưới dạng Mảng
Sử dụng mảng. nguyên mẫu. reduce() để lấy từng giá trị trong đối tượng JSON lồng nhau
Nếu khóa tồn tại trong đối tượng, hãy trả về giá trị đích, nếu không thì trả về null

Khóa đối tượng trong Javascript là gì?

Đối tượng. keys() method trả về một mảng gồm các tên thuộc tính khóa chuỗi có thể đếm được của chính đối tượng đã cho .