JS의 Object 객체의 일부 작동 방법을 설명하는 기사(공유)

奋力向前
풀어 주다: 2021-08-20 10:29:19
앞으로
2096명이 탐색했습니다.

이전 글 "JavaScript의 객체 복사 방식 심층 분석(코드 포함)"에서는 JS의 객체 복사 방식에 대해 알아보았습니다. 다음 기사에서는 JS의 Object 객체의 몇 가지 작동 방법을 소개합니다.

JS의 Object 객체의 일부 작동 방법을 설명하는 기사(공유)

javascriptjavascriptObject一些高效的操作方法

Object.assign()

方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

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 }
로그인 후 복사

Object.create()

方法创建一个新对象,使用现有的对象来提供新创建的对象的proto

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

const m = Object.create(person);
m.name = "chuchur";
m.sayName(); // chuchur
로그인 후 복사

Object.defineProperties()

方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

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"}
로그인 후 복사

Object.defineProperty()

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

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
로그인 후 복사

Object.entries()

方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用for...in循环遍历该对象时返回的顺序一致(区别在于for-in循环也枚举原型链中的属性)。

const obj = { foo: "bar", baz: 42 };
console.log(Object.entries(obj));
//[['foo','bar'],['baz',42]]
로그인 후 복사

Object.keys()

方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in循环遍历该对象时返回的顺序一致 。

// 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']
로그인 후 복사

Object.values()

方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同(区别在于for-in循环枚举原型链中的属性 )。

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;
  };
로그인 후 복사

Object.hasOwnProperty()

方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性。

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
로그인 후 복사

Object.getOwnPropertyDescriptor()

方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
//   configurable: true,
//   enumerable: true,
//   value: 42,
//   writable: true
// }
로그인 후 복사

Object.getOwnPropertyDescriptors()

方法用来获取一个对象的所有自身属性的描述符。

Object.assign()方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性们,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型,该方法配合Object.create() 方法可以实现上面说的这些。

Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);
로그인 후 복사

Object.getOwnPropertyNames()

方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

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"]
로그인 후 복사

Object.getOwnPropertySymbols()

方法返回一个给定对象自身的所有Symbol属性的数组。

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)
로그인 후 복사

Object.isPrototypeOf()

方法用于测试一个对象是否存在于另一个对象的原型链上。

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
로그인 후 복사

Object.propertyIsEnumerable()

方法返回一个布尔值,表示指定的属性是否可枚举。

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
로그인 후 복사

Object.getPrototypeOf()

方法返回指定对象的原型(内部[[Prototype]]

Object.sign()

메서드의 Object에 대한 일부 효율적인 작업 방법은 모든 열거 가능한 속성의 값을 할당하는 데 사용됩니다. 하나 이상의 원본 개체에서 대상 개체로 복사됩니다. 대상 객체를 반환합니다.

const prototype1 = {};
const object1 = Object.create(prototype1);

console.log(Object.getPrototypeOf(object1) === prototype1);
// expected output: true
로그인 후 복사

Object.create()

메서드는 새로 생성된 객체의 proto를 제공하기 위해 기존 객체를 사용하여 새 객체를 생성합니다.

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;
    }
  };
}
로그인 후 복사

Object.defineProperties()

메소드는 새로운 속성을 직접 정의하거나 객체의 기존 속성을 수정하여 객체를 반환합니다.

// 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异常
로그인 후 복사

Object.defineProperty()

이 메서드는 객체에 대한 새 속성을 직접 정의하거나 객체의 기존 속성을 수정하고 객체를 반환합니다.

// 新对象默认是可扩展的.
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
로그인 후 복사

Object.entries()

메서드는 주어진 객체의 열거 가능한 속성에 대한 키-값 쌍의 배열을 반환하며, for...in을 사용하여 객체를 반복할 때 반환되는 것과 동일한 방식으로 정렬됩니다. 순서는 동일합니다(차이점은 for-in 루프도 프로토타입 체인의 속성을 열거한다는 점입니다).

const object1 = {
  property1: 42,
};

const object2 = Object.freeze(object1);

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

console.log(object2.property1);
// 输出: 42
로그인 후 복사

Object.keys()

메서드는 주어진 객체의 자체 열거 가능한 속성으로 구성된 배열을 반환합니다. 배열의 속성 이름 순서와 for...in<의 사용은 다음과 같습니다. /code> 개체를 반복할 때 반환되는 순서는 일관됩니다. <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// 使用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: &quot;plep&quot; }; Object.preventExtensions(nonWritable); Object.defineProperty(nonWritable, &quot;e&quot;, { writable: false }); // 变得不可写 Object.isFrozen(nonWritable); //=== false // 把这个属性改为不可配置,会让这个对象成为冻结对象. Object.defineProperty(nonWritable, &quot;e&quot;, { configurable: false }); // 变得不可配置 Object.isFrozen(nonWritable); //=== true // 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的. var nonConfigurable = { release: &quot;the kraken!&quot; }; Object.preventExtensions(nonConfigurable); Object.defineProperty(nonConfigurable, &quot;release&quot;, { configurable: false }); Object.isFrozen(nonConfigurable); //=== false // 把这个属性改为不可写,会让这个对象成为冻结对象. Object.defineProperty(nonConfigurable, &quot;release&quot;, { writable: false }); Object.isFrozen(nonConfigurable); //=== true // 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的. var accessor = { get food() { return &quot;yum&quot;; }, }; Object.preventExtensions(accessor); Object.isFrozen(accessor); //=== false // ...但把这个属性改为不可配置,会让这个对象成为冻结对象. Object.defineProperty(accessor, &quot;food&quot;, { configurable: false }); Object.isFrozen(accessor); //=== true</pre><div class="contentsignin">로그인 후 복사</div></div></p>Object.values()<h2></h2> 메서드는 주어진 객체 자체의 열거 가능한 모든 속성 값의 배열을 반환합니다. 값의 순서는 <code>for...in<을 사용하는 것과 동일합니다. /code> 루프(차이점은 프로토타입 체인의 속성을 열거하는 <code>for-in 루프로 구성됨)

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
로그인 후 복사

Object.hasOwnProperty()

메서드는 객체의 자체 속성에 지정된 속성이 있는지 여부를 나타내는 부울 값을 반환합니다.

// 新建的对象默认不是密封的.
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 ,访问器属性不考虑可写不可写,只考虑是否可配置
로그인 후 복사

Object.getOwnPropertyDescriptor()

메서드는 지정된 객체의 고유 속성에 해당하는 속성 설명자를 반환합니다. (자체 속성은 객체에 직접 할당된 속성을 말하며 프로토타입 체인에서 조회할 필요가 없습니다.)

// 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
로그인 후 복사
Object.getOwnPropertyDescriptors()🎜🎜 메서드는 객체의 모든 자체 속성에 대한 설명자를 얻는 데 사용됩니다. 객체. 🎜🎜🎜Object.asset() 메서드는 소스 객체의 열거 가능한 자체 속성만 복사할 수 있습니다. 동시에 속성의 속성은 복사하는 동안 복사할 수 없습니다. 또한 접근자 속성은 데이터 속성으로 변환됩니다. 소스 객체의 프로토타입을 복사할 수 없는 경우 이 메서드를 Object.create() 메서드와 함께 사용하여 위의 작업을 수행할 수 있습니다. 🎜🎜rrreee🎜Object.getOwnPropertyNames()🎜🎜 메서드는 지정된 개체의 모든 자체 속성(열거할 수 없는 속성은 포함하지만 Symbol 값이 있는 속성은 제외)의 속성 이름으로 구성된 배열을 반환합니다. 이름으로) . 🎜rrreee🎜Object.getOwnPropertySymbols()🎜🎜 메서드는 지정된 개체 자체의 모든 Symbol 속성 배열을 반환합니다. 🎜rrreee🎜Object.isPrototypeOf()🎜🎜 메소드는 해당 객체가 다른 객체의 프로토타입 체인에 존재하는지 테스트하는 데 사용됩니다. 🎜rrreee🎜Object.propertyIsEnumerable()🎜🎜 메서드는 지정된 속성이 열거 가능한지 여부를 나타내는 부울 값을 반환합니다. 🎜rrreee🎜Object.getPrototypeOf()🎜🎜 메서드는 지정된 개체의 프로토타입(내부 [[Prototype]]) 속성을 반환합니다. 🎜rrreee🎜Object.is()🎜🎜 메서드는 두 값은 같은 값입니다. 🎜rrreee🎜Object.preventExtensions()🎜🎜 메서드는 객체를 확장 불가능하게 만듭니다. 즉, 새 속성을 추가할 수 없습니다. 🎜rrreee🎜Object.isExtensible()🎜🎜 메서드는 객체가 확장 가능한지 여부(새 속성을 객체에 추가할 수 있는지 여부)를 결정합니다. 🎜rrreee🎜Object.freeze()🎜🎜 메서드는 객체를 고정할 수 있습니다. 고정이란 이 객체에 새 속성을 추가할 수 없고, 기존 속성의 값을 수정할 수 없으며, 기존 속성을 삭제할 수 없으며, 객체를 고정할 수 없음을 의미합니다. 속성의 열거 가능성, 구성 가능성 및 쓰기 가능성이 있습니다. 이 메서드는 고정된 개체를 반환합니다. 🎜rrreee🎜Object.isFrozen()🎜🎜 메서드는 객체가 동결되었는지 여부를 결정합니다. 🎜rrreee🎜Object.seal()🎜🎜 메서드는 객체를 봉인하여 새 속성이 추가되는 것을 방지하고 모든 기존 속성을 구성 불가능으로 표시합니다. 현재 속성의 값은 쓰기 가능한 한 변경될 수 있습니다. 🎜rrreee🎜Object.isSealed()🎜🎜 메소드는 객체가 봉인되었는지 여부를 결정합니다. 🎜rrreee🎜Object.valueOf()🎜🎜 메서드는 지정된 개체의 원래 값을 반환합니다. 🎜rrreee🎜추천 학습: 🎜JavaScript 비디오 튜토리얼🎜🎜

위 내용은 JS의 Object 객체의 일부 작동 방법을 설명하는 기사(공유)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:chuchur.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿