Object.keys・Object.values・Object.entries は、オブジェクトの「キー」「値」「キーと値のペア」を配列として取り出すメソッドです。 配列になれば map・filter・sort がそのまま使えるので、オブジェクトのループや加工がぐっと書きやすくなります。加工したあとは Object.fromEntries でオブジェクトに戻せます。

この記事では、よく似た for...in や Object.getOwnPropertyNames との違いを比較表で整理し、すべてのコードに Node.js 22.22.2 での実行結果を付けました。数値キーが先に並ぶ列挙順、null を渡したときの TypeError、キー名変換や並べ替えなどのコピペ集、Map・URLSearchParams との相互変換、ES2024 の Object.groupBy、TypeScript で keys の型が string[] になる件まで、1ページで確認できます。

Object.keys・values・entries の早見表

まずは基本の4つです。入力は const user = { name: "Sato", age: 30, role: "admin" } です。

メソッド 返すもの 実行結果
Object.keys(user) キーの配列 ["name","age","role"]
Object.values(user) 値の配列 ["Sato",30,"admin"]
Object.entries(user) [キー, 値] の配列 [["name","Sato"],["age",30],["role","admin"]]
Object.fromEntries([["a",1],["b",2]]) オブジェクト(entries の逆) {"a":1,"b":2}

次に、似た機能との違いです。「どこまで拾うか」が方法ごとに違います。

方法 戻り値 継承プロパティ Symbol キー 非列挙プロパティ
Object.keys(obj) キーの配列(文字列) 含まない 含まない 含まない
Object.values(obj) 値の配列 含まない 含まない 含まない
Object.entries(obj) [キー, 値] の配列 含まない 含まない 含まない
Object.fromEntries(iterable) 新しいオブジェクト ―(配列などから作る) 入力にあればキーにできる ―
for (const k in obj) なし(1つずつ回す) 含む 含まない 含まない
Object.getOwnPropertyNames(obj) キーの配列(文字列) 含まない 含まない 含む
Object.getOwnPropertySymbols(obj) Symbol の配列 含まない Symbol だけ 含む
Reflect.ownKeys(obj) キーの配列(文字列と Symbol) 含まない 含む 含む

ふだんのループや加工は keys・values・entries の3つで足ります。 「自分自身が持つ、列挙できる、文字列キーのプロパティ」だけを返すので、想定外のものが混ざりにくいのが利点です。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JavaScript Object.keys・values・entries使い方」

検証環境と基本の使い方

実行結果は次の環境で取得しました。

項目 値
Node.js 22.22.2
TypeScript 7.0.2(npm で作業フォルダに導入し、tsc --noEmit で確認)
ブラウザ Chromium 141(Object.groupBy が関数として存在することと、null を渡したときのメッセージのみ確認)

そのほかのブラウザや Node.js のほかのバージョンでは実行していません(未実行)。

いちばん基本のコード

const user = { name: "Sato", age: 30, role: "admin" };

console.log(Object.keys(user));
console.log(Object.values(user));
console.log(Object.entries(user));
console.log(Object.fromEntries([["a", 1], ["b", 2]]));

実行結果:

[ 'name', 'age', 'role' ]
[ 'Sato', 30, 'admin' ]
[ [ 'name', 'Sato' ], [ 'age', 30 ], [ 'role', 'admin' ] ]
{ a: 1, b: 2 }

どれも Object.keys(user) のように Object. から呼びます。user.keys() という書き方はありません(Map や配列の keys() とは別のものです)。

オブジェクトをループする3つの書き方

const price = { apple: 120, banana: 80, cherry: 300 };

// 1. for...of と分割代入(いちばん読みやすい)
for (const [key, value] of Object.entries(price)) {
  console.log(`${key}: ${value}`);
}

// 2. forEach(番号も取れる)
Object.entries(price).forEach(([key, value], i) => {
  console.log(`${i} ${key}=${value}`);
});

実行結果:

apple: 120
banana: 80
cherry: 300
0 apple=120
1 banana=80
2 cherry=300

[key, value] の部分は分割代入(配列の中身を変数に取り出す書き方)です。キーと値の両方を使うなら entries、キーだけなら keys、値だけなら values と使い分けます。

keys・for...in・getOwnPropertyNames の違いを実行して比べる

早見表の内容を、1つのオブジェクトで確かめます。次のオブジェクトは「自分のプロパティ」「継承したプロパティ」「Symbol キー」「非列挙プロパティ」の4種類を持っています。

const sym = Symbol("secret");
const proto = { inherited: "P" };           // 継承元
const obj = Object.create(proto);           // proto を継承したオブジェクト
obj.own = 1;                                // 自分のプロパティ
obj[sym] = "S";                             // Symbol キー
Object.defineProperty(obj, "hidden", { value: "H", enumerable: false }); // 非列挙

console.log(Object.keys(obj));
console.log(Object.values(obj));
console.log(Object.entries(obj));

const viaForIn = [];
for (const k in obj) viaForIn.push(k);
console.log(viaForIn);

console.log(Object.getOwnPropertyNames(obj));
console.log(Object.getOwnPropertySymbols(obj));
console.log(Reflect.ownKeys(obj));

実行結果:

[ 'own' ]
[ 1 ]
[ [ 'own', 1 ] ]
[ 'own', 'inherited' ]
[ 'own', 'hidden' ]
[ Symbol(secret) ]
[ 'own', 'hidden', Symbol(secret) ]
方法 own inherited(継承) hidden(非列挙) Symbol(secret)
Object.keys / values / entries 出る 出ない 出ない 出ない
for...in 出る 出る 出ない 出ない
Object.getOwnPropertyNames 出る 出ない 出る 出ない
Object.getOwnPropertySymbols 出ない 出ない 出ない 出る
Reflect.ownKeys 出る 出ない 出る 出る

for...in を使うときは Object.hasOwn を添える

for...in は継承したプロパティも回します。自分のプロパティだけにしたいときは、Object.hasOwn で確かめます。

const ownOnly = [];
for (const k in obj) {
  if (Object.hasOwn(obj, k)) ownOnly.push(k);
}
console.log(ownOnly);
[ 'own' ]

結果は Object.keys と同じになりました。新しく書くコードでは、for (const k of Object.keys(obj)) のほうが短く、意図も伝わりやすい書き方です。

クラスのインスタンスや配列に使うとどうなるか

class P {
  constructor() { this.n = 1; }
  get g() { return 2; }
  m() {}
}
console.log(Object.keys(new P()));      // インスタンス
console.log(Object.keys([10, 20]));     // 配列
console.log(Object.entries(["x", "y"]));
console.log(Object.keys("abc"));        // 文字列
console.log(Object.keys(123));          // 数値
console.log(Object.keys(new Date()));   // Date
[ 'n' ]
[ '0', '1' ]
[ [ '0', 'x' ], [ '1', 'y' ] ]
[ '0', '1', '2' ]
[]
[]
  • クラスのメソッド(m)とゲッター(g)はプロトタイプ側にあるので、keys には出ません。コンストラクターで this.n に入れたものだけが出ます。
  • 配列に使うと、添字が 文字列 で返ります('0'、'1')。数値として使うときは Number() で変換します。
  • 数値や Date は列挙できる自分のプロパティを持たないので、空の配列になります。

列挙順のルール:数値キーが先に昇順で並ぶ

Object.keys の順番は「書いた順」が基本ですが、数値のように見えるキーだけは先頭に集められ、小さい順に並びます。

const o = {
  b: 1,
  10: "x",
  a: 2,
  2: "y",
  "-1": "neg",
  "01": "z",
  1.5: "f",
  [Symbol("s")]: 0,
  1: "w",
};
console.log(Object.keys(o));
console.log(JSON.stringify(o));

実行結果:

[ '1', '2', '10', 'b', 'a', '-1', '01', '1.5' ]
{"1":"w","2":"y","10":"x","b":1,"a":2,"-1":"neg","01":"z","1.5":"f"}
順番 対象 この例での並び
1 0以上の整数として読めるキー 1、2、10(数値の小さい順。書いた順ではない)
2 そのほかの文字列キー b、a、-1、01、1.5(書いた順)
3 Symbol キー keys・values・entries には出ない

ポイントは次の3つです。

  • 10 を 2 より先に書いても、結果は 1 → 2 → 10 です。文字列としての順(1 → 10 → 2)でもありません。
  • -1、01、1.5 は「0以上の整数」の形ではないので、ふつうの文字列キーとして書いた順に並びます。
  • JSON.stringify も同じ順番で出力します。values と entries も keys と同じ順です。

書いた順を保ちたいときは Map を使う

ID のような数値をキーにして、登録した順を保ちたいときは Map が向いています。

const m = new Map([["b", 1], [10, "x"], ["a", 2], [2, "y"]]);
console.log([...m.keys()]);
[ 'b', 10, 'a', 2 ]

Map は入れた順のままで、キーの型(数値の 10)も保たれます。オブジェクトでは、キーはすべて文字列(または Symbol)になります。

null や undefined を渡すと TypeError になる

API の応答がまだ届いていないときなど、変数が null や undefined のまま Object.keys に渡ると、エラーで止まります。

Object.keys(null);
Object.keys(undefined);
Object.values(null);
Object.entries(undefined);

実行結果(Node.js 22.22.2。Chromium 141 でも Object.keys(null) は同じメッセージでした):

TypeError: Cannot convert undefined or null to object

4つとも同じメッセージです。Object.fromEntries は、渡したものによってメッセージが変わります。

呼び出し 実行結果
Object.fromEntries(null) TypeError: undefined is not iterable
Object.fromEntries({a:1}) TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Object.fromEntries([1,2]) TypeError: Iterator value 1 is not an entry object
Object.fromEntries([["a",1],["a",2]]) {"a":2}(同じキーは後の値が残る)
for (const k in null) {} エラーにならず、ループが0回

fromEntries に渡すのは 「[キー, 値] のペアを並べた配列(または Map などの反復できるもの)」 です。オブジェクトをそのまま渡すとエラーになるので、先に Object.entries で配列にします。

直す前と後

// 直す前:data が null だと TypeError で止まる
const keys1 = Object.keys(data);

// 直した後:?? で空のオブジェクトに置き換える
const keys2 = Object.keys(data ?? {});

Object.keys(null ?? {}) の実行結果は [] でした。?? は「左側が null か undefined のときだけ右側を使う」演算子です。外から受け取ったデータに使うときは ?? {} を添えると、空の配列として安全に処理を続けられます。

やりたいこと別コピペ集

ここからは用途別のコードです。入力は次の price を使います。

const price = { apple: 120, banana: 80, cherry: 300 };

加工の基本形は 「entries で配列にする → map・filter・sort で加工 → fromEntries でオブジェクトに戻す」 の3段階です。

flowchart LR
  A["オブジェクト"] -->|Object.entries| B["[キー, 値] の配列"]
  B -->|"map / filter / sort"| C["加工後の配列"]
  C -->|Object.fromEntries| D["新しいオブジェクト"]

逆引き早見表

やりたいこと コード 実行結果
件数を数える Object.keys(price).length 3
空かどうか調べる Object.keys({}).length === 0 true
値を合計する Object.values(price).reduce((s, v) => s + v, 0) 500
最大値を出す Math.max(...Object.values(price)) 300
値からキーを探す Object.keys(price).find(k => price[k] === 80) "banana"
ある値を含むか調べる Object.values(price).includes(300) true
値がいちばん大きい組を取る Object.entries(price).sort(([, a], [, b]) => b - a)[0] ["cherry",300]

キー名を変換する(スネークケース → キャメルケース)

const row = { user_name: "Sato", mail_address: "a@example.com" };
const camel = Object.fromEntries(
  Object.entries(row).map(([k, v]) => [
    k.replace(/_([a-z])/g, (_, c) => c.toUpperCase()),
    v,
  ])
);
console.log(camel);
{ userName: 'Sato', mailAddress: 'a@example.com' }

値を一括で加工する

const withTax = Object.fromEntries(
  Object.entries(price).map(([k, v]) => [k, Math.round(v * 1.1)])
);
console.log(withTax);
{ apple: 132, banana: 88, cherry: 330 }

条件で絞り込む

// 値が 100 以上のものだけ残す
const expensive = Object.fromEntries(
  Object.entries(price).filter(([, v]) => v >= 100)
);

// 指定したキーだけ取り出す(pick)
const picked = Object.fromEntries(["apple", "cherry"].map((k) => [k, price[k]]));

// 指定したキーを除く(omit)
const omitted = Object.fromEntries(
  Object.entries(price).filter(([k]) => !["banana"].includes(k))
);

// null と undefined の項目を取り除く
const cleaned = Object.fromEntries(
  Object.entries({ a: 1, b: null, c: undefined, d: "", e: 0 }).filter(([, v]) => v != null)
);
console.log(expensive, picked, omitted, cleaned);
{ apple: 120, cherry: 300 } { apple: 120, cherry: 300 } { apple: 120, cherry: 300 } { a: 1, d: '', e: 0 }

([, v]) は「1つ目(キー)は使わず、2つ目(値)だけ受け取る」という書き方です。最後の例の v != null は null と undefined の両方を除き、空文字と 0 は残します。

並べ替える

// 値の大きい順
const byValue = Object.fromEntries(
  Object.entries(price).sort(([, a], [, b]) => b - a)
);

// キーの文字順
const byKey = Object.fromEntries(
  Object.entries({ b: 1, c: 2, a: 3 }).sort(([a], [b]) => a.localeCompare(b))
);
console.log(byValue, byKey);
{ cherry: 300, apple: 120, banana: 80 } { a: 3, b: 1, c: 2 }

キーが数値の形のときは、fromEntries で戻すと数値の昇順に並び直されます(前の章の列挙順のルール)。その場合は、オブジェクトに戻さず配列のまま使うか、Map にします。

キーと値を入れ替える

const inverted = Object.fromEntries(
  Object.entries({ a: "x", b: "y" }).map(([k, v]) => [v, k])
);
console.log(inverted);
{ x: 'a', y: 'b' }

値が重複していると、後のものが残ります(fromEntries は同じキーを上書きするため)。

配列からオブジェクトを作る

// ID をキーにした対応表にする
const users = [{ id: 1, n: "A" }, { id: 2, n: "B" }];
const byId = Object.fromEntries(users.map((u) => [u.id, u]));

// キーの配列と値の配列を組み合わせる
const zipped = Object.fromEntries(["a", "b"].map((k, i) => [k, [1, 2][i]]));
console.log(byId, zipped);
{ '1': { id: 1, n: 'A' }, '2': { id: 2, n: 'B' } } { a: 1, b: 2 }

入れ子のオブジェクトを回す

const nested = { a: { x: 1 }, b: { x: 2 } };
console.log(Object.entries(nested).map(([k, { x }]) => `${k}:${x}`));

// entries → fromEntries は浅いコピー
const copy = Object.fromEntries(Object.entries(nested));
copy.a.x = 99;
console.log(nested.a.x);
[ 'a:1', 'b:2' ]
99

コピー側を書き換えると、元の nested.a.x も 99 になりました。entries と fromEntries で作ったオブジェクトは、1階層目だけが新しく、内側のオブジェクトは元と共有されます。 内側まで別物にしたいときは structuredClone(nested) が使えます(Node.js 22.22.2 で、入れ子のオブジェクトが複製されることを確認しました)。

Map・URLSearchParams との相互変換

entries と fromEntries は、ほかのデータ構造との橋渡しにも使えます。

変換 コード
オブジェクト → Map new Map(Object.entries(obj))
Map → オブジェクト Object.fromEntries(map)
オブジェクト → クエリ文字列 new URLSearchParams(obj).toString()
クエリ文字列 → オブジェクト Object.fromEntries(new URLSearchParams(str))
const mp = new Map(Object.entries(price));
console.log(mp);
console.log(Object.fromEntries(mp));

const ps = new URLSearchParams({ q: "js object", page: 2 });
console.log(ps.toString());

console.log(Object.fromEntries(new URLSearchParams("q=js&page=2&tag=a&tag=b")));

実行結果:

Map(3) { 'apple' => 120, 'banana' => 80, 'cherry' => 300 }
{ apple: 120, banana: 80, cherry: 300 }
q=js+object&page=2
{ q: 'js', page: '2', tag: 'b' }

気をつけたい点が2つあります。

  • クエリ文字列から作った値はすべて文字列です(page は '2')。数値として使うときは Number() で変換します。
  • 同じ名前のパラメーターが複数あると、最後の1つだけが残ります(tag は 'b')。全部ほしいときは params.getAll("tag") を使います(実行結果は [ 'a', 'b' ] でした)。

フォームの FormData も同じ形([名前, 値] の並び)なので、Object.fromEntries(new FormData(form)) でオブジェクトにする書き方が一般に知られています(ブラウザでの実行は今回未実行です)。

Object.groupBy でグループ分けする(ES2024)

Object.groupBy は、配列の要素をキーごとにまとめたオブジェクトを作るメソッドです。ES2024 で加わりました。Node.js 22.22.2 で動作し、Chromium 141 でも関数として存在することを確認しています。

const items = [
  { name: "pen", cat: "stationery" },
  { name: "note", cat: "stationery" },
  { name: "cup", cat: "kitchen" },
];
const groups = Object.groupBy(items, (i) => i.cat);
console.log(groups);

// グループごとの件数
console.log(
  Object.fromEntries(Object.entries(groups).map(([k, v]) => [k, v.length]))
);

実行結果:

[Object: null prototype] {
  stationery: [
    { name: 'pen', cat: 'stationery' },
    { name: 'note', cat: 'stationery' }
  ],
  kitchen: [ { name: 'cup', cat: 'kitchen' } ]
}
{ stationery: 2, kitchen: 1 }

[Object: null prototype] と表示されているとおり、groupBy の戻り値はプロトタイプを持たないオブジェクトです(Object.getPrototypeOf(groups) === null は true でした)。そのため groups.hasOwnProperty("kitchen") のようなメソッド呼び出しは使えません。キーの有無は Object.hasOwn(groups, "kitchen") や "kitchen" in groups で調べます(どちらも true を返し、typeof groups.hasOwnProperty は undefined でした)。Object.keys や Object.entries は、上の例のとおり問題なく使えます。

キーを文字列以外(数値やオブジェクト)にしたいときは Map.groupBy が使えます。

console.log(Map.groupBy(items, (i) => i.cat.length));
Map(2) {
  10 => [
    { name: 'pen', cat: 'stationery' },
    { name: 'note', cat: 'stationery' }
  ],
  7 => [ { name: 'cup', cat: 'kitchen' } ]
}

TypeScript では Object.keys の型が string[] になる

TypeScript で Object.keys を使うと、戻り値の型は string[] です。("name" | "age")[] のような、キー名に絞った型にはなりません。そのため、次のコードは型エラーになります。

const user = { name: "Sato", age: 30 };
const keys = Object.keys(user);

for (const k of Object.keys(user)) {
  console.log(user[k]);       // ここでエラー
}

const first: "name" = keys[0]; // ここでもエラー

npx tsc --noEmit --strict --target es2024 の実行結果(TypeScript 7.0.2):

k.ts(4,15): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; age: number; }'.
  No index signature with a parameter of type 'string' was found on type '{ name: string; age: number; }'.
k.ts(16,7): error TS2322: Type 'string' is not assignable to type '"name"'.

なぜ string[] なのか

TypeScript の型は「少なくともこのプロパティを持つ」という意味で、実際のオブジェクトがそれ以外のプロパティを持つことを許しています。たとえば { name, age, role } を持つオブジェクトも、{ name, age } 型の変数に入れられます。そのため、実行時に Object.keys が返すキーが型に書かれたものだけとは限らず、TypeScript は安全側の string[] を返すようにしています。

書き方の選択肢

書き方 コード 向いている場面
型アサーション Object.keys(user) as (keyof typeof user)[] オブジェクトを自分で作っていて、余分なキーがないとわかっている
小さな関数にまとめる 下の typedKeys 何度も使う
entries を使う for (const [k, v] of Object.entries(user)) 値だけ使えれば足りる(k は string、v は string | number)
function typedKeys<T extends object>(o: T): (keyof T)[] {
  return Object.keys(o) as (keyof T)[];
}

for (const k of typedKeys(user)) {
  console.log(user[k]); // エラーなし
}

上の2つの書き方(型アサーションと typedKeys)は、tsc --noEmit でエラーが出ないことを確認しました。Object.entries の分割代入も、k を string、v を string | number として受け取れました。

groupBy と target の設定

Object.groupBy は、tsconfig の target(または lib)が es2024 以降のときに型が使えます。es2020 で同じコードを通すと、次のエラーになりました。

k.ts(17,18): error TS2550: Property 'groupBy' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2024' or later.

また、es2024 にしても、グループを取り出す箇所では次のエラーが出ます。

const g = Object.groupBy([{ c: "x" as const, n: 1 }], (i) => i.c);
const len: number = g.x.length;
k.ts(18,20): error TS18048: 'g.x' is possibly 'undefined'.

該当する要素が1つもないグループは作られないため、型の上では「あるかもしれないし、ないかもしれない」と扱われます。g.x?.length ?? 0 のように書くと、tsc --noEmit がエラーなしで通りました。

つまずきやすい点のチェックリスト

起きること 原因 対処
TypeError: Cannot convert undefined or null to object null・undefined を渡した Object.keys(data ?? {})
TypeError: object is not iterable fromEntries にオブジェクトを渡した 先に Object.entries(obj) で配列にする
キーの順番が書いた順と違う 数値の形のキーは昇順で先頭に並ぶ 順番が大事なら Map か配列を使う
配列の添字が文字列になる keys は常に文字列を返す Number(k) で変換、または配列の keys() や entries() を使う
メソッドやゲッターが出てこない プロトタイプ側にあるため 必要なら Object.getOwnPropertyNames(Object.getPrototypeOf(obj))
for...in で余分なキーが出る 継承プロパティも回る Object.keys に変える、または Object.hasOwn で確認
コピーしたはずが元も変わる entries → fromEntries は浅いコピー 入れ子は structuredClone などで複製
クエリ文字列の値が数値にならない URLSearchParams の値は文字列 Number() で変換

よくある質問

Q. Object.keys と for...in はどちらを使えばよいですか? A. Object.keys(または entries)がおすすめです。自分自身のプロパティだけを配列で返すので、map や filter にそのままつなげられます。for...in は継承したプロパティも回すため、使うときは Object.hasOwn での確認を添えます。

Q. Object.entries の順番は保証されていますか? A. この記事の実行結果のとおり、0以上の整数として読めるキーが数値の昇順で先に並び、そのあとにほかの文字列キーが書いた順で続きます。keys・values・entries・JSON.stringify で同じ順でした。登録順をそのまま保ちたいときは Map が向いています。

Q. Object.fromEntries はいつから使えますか? A. ES2019 で加わったメソッドです。keys は ES5、values と entries は ES2017、Object.hasOwn は ES2022、Object.groupBy は ES2024 で加わったものとして一般に知られています。この記事では Node.js 22.22.2 ですべて動作を確認しました。

Q. Symbol のキーも含めて取り出すにはどうしますか? A. Reflect.ownKeys(obj) を使うと、文字列キーと Symbol キーの両方(非列挙のものも含む)が配列で返ります。Symbol だけなら Object.getOwnPropertySymbols(obj) です。

まとめ

  • keys はキー、values は値、entries は [キー, 値] の配列を返す。 fromEntries はその逆で、ペアの配列からオブジェクトを作る。
  • 3つとも「自分自身の・列挙できる・文字列キー」だけを返す。 for...in は継承分も回し、getOwnPropertyNames は非列挙も含む。
  • 列挙順は「数値の形のキーが昇順で先、残りは書いた順」。 順番を保ちたいデータは Map か配列で持つ。
  • null・undefined を渡すと TypeError。 外から来たデータには ?? {} を添える。
  • 加工は「entries → map / filter / sort → fromEntries」の3段階。 キー名変換・絞り込み・並べ替え・入れ替えがこの形で書ける。
  • Map や URLSearchParams とは entries / fromEntries で相互に変換できる。 クエリ文字列の値は文字列、同名パラメーターは最後の1つが残る。
  • TypeScript では keys の型は string[]。 キー名の型がほしいときは keyof を使った型アサーションか、entries を使う。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JavaScript Object.keys・values・entries使い方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?