Table of Contents
Object.assign()
Object.create()
Object.defineProperties()
Object.defineProperty()
Object.entries()
Object.keys()
Object.values()
Object.hasOwnProperty()
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.isPrototypeOf()
Object.propertyIsEnumerable()
Object.getPrototypeOf()
) property of the specified object. ()
Object.preventExtensions()
Object.isExtensible()
Object.freeze()
Object.isFrozen()
Object.seal()
Object.isSealed()
Object.valueOf()
Home Web Front-end JS Tutorial An article explaining some operating methods of Object objects in JS (share)

An article explaining some operating methods of Object objects in JS (share)

Aug 20, 2021 am 10:27 AM
java javascript js

In the previous article "In-depth analysis of the object copy method in JavaScript (with code)", we learned about the object copy method in JS. The following article will introduce you to some operating methods of Object objects in JS. Let’s take a look.

An article explaining some operating methods of Object objects in JS (share)

javascriptObjectSome efficient operation methods

Object.assign()

Method is used to copy the values ​​of all enumerable properties from one or more source objects to the target object. It will return the target object. The

const object1 = { a: 1, b: 2, c: 3 };
const object2 = Object.assign({ c: 4, d: 5 }, object1);
console.log(object2); // {  a: 1,  b: 2,  c: 3 ,c: 4, d: 5 }
Copy after login

Object.create()

method creates a new object, using an existing object to provide the proto of the newly created object.

const person = {
  color: "red",
  sayName: function () {
    console.log(this.name);
  },
};

const m = Object.create(person);
m.name = "chuchur";
m.sayName(); // chuchur
Copy after login

Object.defineProperties()

The method directly defines new properties or modifies existing properties on an object, and returns the object.

var obj = {};
Object.defineProperties(obj, {
  property1: {
    value: 1,
    writable: true,
  },
  property2: {
    value: "Hello",
    writable: false,
  },
});

obj.property1 = 1;
obj.property2 = 2;

console.log(obj); // {property1: 1, property2: "Hello"}
Copy after login

Object.defineProperty()

The method will directly define a new property on an object, or modify an existing property of an object, and return the object.

var o = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value: 37,
  writable: true,
  enumerable: true,
  configurable: true,
});

// 对象o拥有了属性a,值为37

// 在对象中添加一个属性与存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
  get: function () {
    return bValue;
  },
  set: function (newValue) {
    bValue = newValue;
  },
  enumerable: true,
  configurable: true,
});

o.b = 38;
// 对象o拥有了属性b,值为38

// o.b的值现在总是与bValue相同,除非重新定义o.b
Copy after login

Object.entries()

The method returns an array of key-value pairs for the given object's own enumerable properties, arranged and used for...in The order returned when looping through the object is the same (the difference is that the for-in loop also enumerates the properties in the prototype chain).

const obj = { foo: "bar", baz: 42 };
console.log(Object.entries(obj));
//[['foo','bar'],['baz',42]]
Copy after login

Object.keys()

The method will return an array consisting of the self-enumerable properties of a given object. The order of the property names in the array and the use of for ...inThe order returned when looping through the object is consistent.

// simple array
var arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// array like object
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// array like object with random key ordering
var anObj = { 100: "a", 2: "b", 7: "c" };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// getFoo is a property which isn't enumerable
var myObj = Object.create(
  {},
  {
    getFoo: {
      value: function () {
        return this.foo;
      },
    },
  }
);
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']
Copy after login

Object.values()

The method returns an array of all enumerable property values ​​​​of a given object itself, in the same order as using for...inThe order of the loop is the same (the difference is that the for-in loop enumerates the properties in the prototype chain).

var obj = { foo: "bar", baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// array like object
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.values(obj)); // ['a', 'b', 'c']

// array like object with random key ordering
// when we use numeric keys, the value returned in a numerical order according to the keys
var an_obj = { 100: "a", 2: "b", 7: "c" };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// getFoo is property which isn't enumerable
var my_obj = Object.create(
  {},
  {
    getFoo: {
      value: function () {
        return this.foo;
      },
    },
  }
);
my_obj.foo = "bar";
console.log(Object.values(my_obj)); // ['bar']

// non-object argument will be coerced to an object
console.log(Object.values("foo")); // ['f', 'o', 'o'] ==Array.from('foo')

//ES5
if (!Object.values)
  Object.values = function (obj) {
    if (obj !== Object(obj))
      throw new TypeError("Object.values called on a non-object");
    var val = [],
      key;
    for (key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        val.push(obj[key]);
      }
    }
    return val;
  };
Copy after login

Object.hasOwnProperty()

The method returns a Boolean value indicating whether the object has the specified property in its own properties.

o = new Object();
o.prop = "exists";

function changeO() {
  o.newprop = o.prop;
  delete o.prop;
}

o.hasOwnProperty("prop"); // 返回 true
changeO();
o.hasOwnProperty("prop"); // 返回 false
o.hasOwnProperty("toString"); // 返回 false
o.hasOwnProperty("hasOwnProperty"); // 返回 false
Copy after login

Object.getOwnPropertyDescriptor()

The method returns the property descriptor corresponding to an own property on the specified object. (Own properties refer to properties that are directly assigned to the object and do not need to be searched from the prototype chain)

o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
//   configurable: true,
//   enumerable: true,
//   value: 42,
//   writable: true
// }
Copy after login

Object.getOwnPropertyDescriptors()

The method is used to obtain the properties of an object Descriptors for all self-properties.

The Object.assign() method can only copy the enumerable self-properties of the source object. At the same time, the properties of the properties cannot be copied during copying, and the accessor properties will be converted into data properties. The prototype of the source object cannot be copied. This method can be used in conjunction with the Object.create() method to achieve the above.

Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);
Copy after login

Object.getOwnPropertyNames()

The method returns a property name of all the own properties of the specified object (including non-enumerable properties but excluding Symbol value as an attribute of the name).

var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]

// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]

// 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function (val, idx, array) {
  console.log(val + " -> " + obj[val]);
});
// 输出
// 0 -> a
// 1 -> b
// 2 -> c

//不可枚举属性
var my_obj = Object.create(
  {},
  {
    getFoo: {
      value: function () {
        return this.foo;
      },
      enumerable: false,
    },
  }
);
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]
Copy after login

Object.getOwnPropertySymbols()

method returns an array of all Symbol properties of the given object itself.

var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols.length); // 2
console.log(objectSymbols); // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]); // Symbol(a)
Copy after login

Object.isPrototypeOf()

The method is used to test whether an object exists on the prototype chain of another object.

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
Copy after login

Object.propertyIsEnumerable()

The method returns a Boolean value indicating whether the specified property is enumerable.

var o = {};
var a = [];
o.prop = "is enumerable";
a[0] = "is enumerable";

o.propertyIsEnumerable("prop"); //  返回 true
a.propertyIsEnumerable(0); // 返回 true

//用户自定义对象和引擎内置对象
var a = ["is enumerable"];

a.propertyIsEnumerable(0); // 返回 true
a.propertyIsEnumerable("length"); // 返回 false

Math.propertyIsEnumerable("random"); // 返回 false
this.propertyIsEnumerable("Math"); // 返回 false

//自身属性和继承属性
var a = [];
a.propertyIsEnumerable("constructor"); // 返回 false

function firstConstructor() {
  this.property = "is not enumerable";
}

firstConstructor.prototype.firstMethod = function () {};

function secondConstructor() {
  this.method = function method() {
    return "is enumerable";
  };
}

secondConstructor.prototype = new firstConstructor();
secondConstructor.prototype.constructor = secondConstructor;

var o = new secondConstructor();
o.arbitraryProperty = "is enumerable";

o.propertyIsEnumerable("arbitraryProperty"); // 返回 true
o.propertyIsEnumerable("method"); // 返回 true
o.propertyIsEnumerable("property"); // 返回 false

o.property = "is enumerable";

o.propertyIsEnumerable("property"); // 返回 true

// 这些返回fasle,是因为,在原型链上propertyIsEnumerable不被考虑
// (尽管最后两个在for-in循环中可以被循环出来)。
o.propertyIsEnumerable("prototype"); // 返回 false (根据 JS 1.8.1/FF3.6)
o.propertyIsEnumerable("constructor"); // 返回 false
o.propertyIsEnumerable("firstMethod"); // 返回 false
Copy after login

Object.getPrototypeOf()

The method returns the <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>const prototype1 = {}; const object1 = Object.create(prototype1); console.log(Object.getPrototypeOf(object1) === prototype1); // expected output: true</pre><div class="contentsignin">Copy after login</div></div>Object.is of the prototype (

internal [[Prototype]]

) property of the specified object. ()

method determines whether two values ​​are the same value.

Object.is("foo", "foo"); // true
Object.is(window, window); // true

Object.is("foo", "bar"); // false
Object.is([], []); // false

var test = { a: 1 };
Object.is(test, test); // true

Object.is(null, null); // true

// 特例
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0 / 0); // true

// ES5
if (!Object.is) {
  Object.is = function (x, y) {
    // SameValue algorithm
    if (x === y) {
      // Steps 1-5, 7-10
      // Steps 6.b-6.e: +0 != -0
      return x !== 0 || 1 / x === 1 / y;
    } else {
      // Step 6.a: NaN == NaN
      return x !== x && y !== y;
    }
  };
}
Copy after login

Object.preventExtensions()

The method makes an object non-extensible, that is, new properties can never be added.

// Object.preventExtensions将原对象变的不可扩展,并且返回原对象.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2; // true

// 字面量方式定义的对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); //=== true

// ...但可以改变.
Object.preventExtensions(empty);
Object.isExtensible(empty); //=== false

// 使用Object.defineProperty方法为一个不可扩展的对象添加新属性会抛出异常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出TypeError异常

// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出TypeError异常.
function fail() {
  "use strict";
  nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();

// 一个不可扩展对象的原型是不可更改的,__proto__是个非标准魔法属性,可以更改一个对象的原型.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // 抛出TypeError异常
Copy after login

Object.isExtensible()

The method determines whether an object is extensible (whether new properties can be added to it).

// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // === true

// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false

// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false

// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false
Copy after login

Object.freeze()

The method can freeze an object. Freezing means that new attributes cannot be added to this object, the values ​​of existing attributes cannot be modified, and existing attributes cannot be deleted. Properties, and the enumerability, configurability, and writability of existing properties of the object cannot be modified. This method returns the frozen object.

const object1 = {
  property1: 42,
};

const object2 = Object.freeze(object1);

object2.property1 = 33;
// 严格模式会报错,非严格模式不报错,但是不执行

console.log(object2.property1);
// 输出: 42
Copy after login

Object.isFrozen()

Method to determine whether an object is frozen.

// 使用Object.freeze是冻结一个对象最方便的方法.
var frozen = { 1: 81 };
Object.isFrozen(frozen); //=== false
Object.freeze(frozen);
Object.isFrozen(frozen); //=== true

// 一个冻结对象也是一个密封对象.
Object.isSealed(frozen); //=== true

// 当然,更是一个不可扩展的对象.
Object.isExtensible(frozen); //=== false

// 一个对象默认是可扩展的,所以它也是非冻结的.
Object.isFrozen({}); // === false

// 一个不可扩展的空对象同时也是一个冻结对象.
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen); //=== true;

// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp); //=== false

// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为p属性仍然是可以配置的(而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp); //=== false

// ...如果删除了这个属性,则它会成为一个冻结对象.
delete oneProp.p;
Object.isFrozen(oneProp); //=== true

// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的.
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable); //=== false

// 把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable); //=== true

// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的.
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable); //=== false

// 把这个属性改为不可写,会让这个对象成为冻结对象.
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable); //=== true

// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的.
var accessor = {
  get food() {
    return "yum";
  },
};
Object.preventExtensions(accessor);
Object.isFrozen(accessor); //=== false

// ...但把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor); //=== true
Copy after login

Object.seal()

The method seals an object, preventing new properties from being added and marking all existing properties as non-configurable. The value of the current property can be changed as long as it is writable.

const object1 = {
  property1: 42,
};

Object.seal(object1);
object1.property1 = 33;
console.log(object1.property1);
// expected output: 33

delete object1.property1; // cannot delete when sealed
console.log(object1.property1);
// expected output: 33
Copy after login

Object.isSealed()

Method to determine whether an object is sealed.

// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // === false

// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true

// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的.
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false

// 如果把这个属性变的不可配置,则这个对象也就成了密封对象.
Object.defineProperty(hasProp, "fee", { configurable: false });
Object.isSealed(hasProp); // === true

// 最简单的方法来生成一个密封对象,当然是使用Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true

// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed); // === false

// 一个密封对象也可以是一个冻结对象,但不是必须的.
Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 属性"p"可写

var s3 = Object.seal({
  get p() {
    return 0;
  },
});
Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置
Copy after login

Object.valueOf()

The method returns the original value of the specified object.

// Array:返回数组对象本身
var array = ["ABC", true, 12, -5];
console.log(array.valueOf() === array); // true

// Date:当前时间距1970年1月1日午夜的毫秒数
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
console.log(date.valueOf()); // 1376838719230

// Number:返回数字值
var num = 15.2654;
console.log(num.valueOf()); // 15.2654

// 布尔:返回布尔值true或false
var bool = true;
console.log(bool.valueOf() === bool); // true

// new一个Boolean对象
var newBool = new Boolean(true);
// valueOf()返回的是true,两者的值相等
console.log(newBool.valueOf() == newBool); // true
// 但是不全等,两者类型不相等,前者是boolean类型,后者是object类型
console.log(newBool.valueOf() === newBool); // false

// Function:返回函数本身
function foo() {}
console.log(foo.valueOf() === foo); // true
var foo2 = new Function("x", "y", "return x + y;");
console.log(foo2.valueOf());
/*
ƒ anonymous(x,y
) {
return x + y;
}
*/

// Object:返回对象本身
var obj = { name: "张三", age: 18 };
console.log(obj.valueOf() === obj); // true

// String:返回字符串值
var str = "http://www.xyz.com";
console.log(str.valueOf() === str); // true

// new一个字符串对象
var str2 = new String("http://www.xyz.com");
// 两者的值相等,但不全等,因为类型不同,前者为string类型,后者为object类型
console.log(str2.valueOf() === str2); // false
Copy after login

Recommended learning: JavaScript video tutorial

The above is the detailed content of An article explaining some operating methods of Object objects in JS (share). For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Java Spring Interview Questions Java Spring Interview Questions Aug 30, 2024 pm 04:29 PM

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Break or return from Java 8 stream forEach? Break or return from Java 8 stream forEach? Feb 07, 2025 pm 12:09 PM

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

TimeStamp to Date in Java TimeStamp to Date in Java Aug 30, 2024 pm 04:28 PM

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Java Program to Find the Volume of Capsule Java Program to Find the Volume of Capsule Feb 07, 2025 am 11:37 AM

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

PHP vs. Python: Understanding the Differences PHP vs. Python: Understanding the Differences Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP: A Key Language for Web Development PHP: A Key Language for Web Development Apr 13, 2025 am 12:08 AM

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

Create the Future: Java Programming for Absolute Beginners Create the Future: Java Programming for Absolute Beginners Oct 13, 2024 pm 01:32 PM

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.

How to Run Your First Spring Boot Application in Spring Tool Suite? How to Run Your First Spring Boot Application in Spring Tool Suite? Feb 07, 2025 pm 12:11 PM

Spring Boot simplifies the creation of robust, scalable, and production-ready Java applications, revolutionizing Java development. Its "convention over configuration" approach, inherent to the Spring ecosystem, minimizes manual setup, allo

See all articles