浓烈之创设对象的有余措施以致优短处,浓厚之继续的种种措施和优短处

浓烈之创设对象的有余措施以致优短处,浓厚之继续的种种措施和优短处

JavaScript 深刻之继续的二种办法和优短处

2017/05/28 · JavaScript
· 继承

原稿出处: 冴羽   

JavaScript 深切之创制对象的有余办法以至优劣势

2017/05/28 · JavaScript
· 对象

初稿出处: 冴羽   

写在后边

正文讲授JavaScript各样世襲格局和优劣点。

唯独注意:

那篇文章更疑似笔记,哎,再让自家惊讶一句:《JavaScript高等程序设计》写得真是太好了!

写在前面

那篇文章讲明创制对象的各种法子,以至优短处。

可是注意:

那篇小说更疑似笔记,因为《JavaScript高端程序设计》写得真是太好了!

1.原型链继承

function Parent () { this.name = ‘kevin’; } Parent.prototype.getName =
function () { console.log(this.name); } function Child () { }
Child.prototype = new Parent(); var child1 = new Child();
console.log(child1.getName()) // kevin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Parent () {
    this.name = ‘kevin’;
}
 
Parent.prototype.getName = function () {
    console.log(this.name);
}
 
function Child () {
 
}
 
Child.prototype = new Parent();
 
var child1 = new Child();
 
console.log(child1.getName()) // kevin

问题:

1.援引类型的属性被全数实例分享,举个例证:

function Parent () { this.names = [‘kevin’, ‘daisy’]; } function Child
() { } Child.prototype = new Parent(); var child1 = new Child();
child1.names.push(‘yayu’); console.log(child1.names); // [“kevin”,
“daisy”, “yayu”] var child2 = new Child(); console.log(child2.names);
// [“kevin”, “daisy”, “yayu”]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Parent () {
    this.names = [‘kevin’, ‘daisy’];
}
 
function Child () {
 
}
 
Child.prototype = new Parent();
 
var child1 = new Child();
 
child1.names.push(‘yayu’);
 
console.log(child1.names); // ["kevin", "daisy", "yayu"]
 
var child2 = new Child();
 
console.log(child2.names); // ["kevin", "daisy", "yayu"]

2.在开创 Child 的实例时,不能够向Parent传参

1. 工厂情势

function createPerson(name) { var o = new Object(); o.name = name;
o.getName = function () { console.log(this.name); }; return o; } var
person1 = createPerson(‘kevin’);

1
2
3
4
5
6
7
8
9
10
11
function createPerson(name) {
    var o = new Object();
    o.name = name;
    o.getName = function () {
        console.log(this.name);
    };
 
    return o;
}
 
var person1 = createPerson(‘kevin’);

症结:对象不恐怕甄别,因为具有的实例都针对叁个原型

2.借出构造函数(优质一而再三回九转卡塔尔(قطر‎

function Parent () { this.names = [‘kevin’, ‘daisy’]; } function Child
() { Parent.call(this); } var child1 = new Child();
child1.names.push(‘yayu’); console.log(child1.names); // [“kevin”,
“daisy”, “yayu”] var child2 = new Child(); console.log(child2.names);
// [“kevin”, “daisy”]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Parent () {
    this.names = [‘kevin’, ‘daisy’];
}
 
function Child () {
    Parent.call(this);
}
 
var child1 = new Child();
 
child1.names.push(‘yayu’);
 
console.log(child1.names); // ["kevin", "daisy", "yayu"]
 
var child2 = new Child();
 
console.log(child2.names); // ["kevin", "daisy"]

优点:

1.防止了引用类型的属性被全数实例分享

2.可以在 Child 中向 Parent 传参

举个例证:

function Parent (name) { this.name = name; } function Child (name) {
Parent.call(this, name); } var child1 = new Child(‘kevin’);
console.log(child1.name); // kevin var child2 = new Child(‘daisy’);
console.log(child2.name); // daisy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Parent (name) {
    this.name = name;
}
 
function Child (name) {
    Parent.call(this, name);
}
 
var child1 = new Child(‘kevin’);
 
console.log(child1.name); // kevin
 
var child2 = new Child(‘daisy’);
 
console.log(child2.name); // daisy

缺点:

主意都在布局函数中定义,每回创设实例都会创立一遍方法。

2. 构造函数形式

function Person(name) { this.name = name; this.getName = function () {
console.log(this.name); }; } var person1 = new Person(‘kevin’);

1
2
3
4
5
6
7
8
function Person(name) {
    this.name = name;
    this.getName = function () {
        console.log(this.name);
    };
}
 
var person1 = new Person(‘kevin’);

可取:实例能够辨认为多个特定的等级次序

缺欠:每一遍创立实例时,各种方法都要被创设一回

3.构成世袭

原型链世袭和经文一而再一而再再而三双剑合璧。

function Parent (name) { this.name = name; this.colors = [‘red’,
‘blue’, ‘green’]; } Parent.prototype.getName = function () {
console.log(this.name) } function Child (name, age) { Parent.call(this,
name); this.age = age; } Child.prototype = new Parent(); var child1 =
new Child(‘kevin’, ’18’); child1.colors.push(‘black’);
console.log(child1.name); // kevin console.log(child1.age); // 18
console.log(child1.colors); // [“red”, “blue”, “green”, “black”] var
child2 = new Child(‘daisy’, ’20’); console.log(child2.name); // daisy
console.log(child2.age); // 20 console.log(child2.colors); // [“red”,
“blue”, “green”]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function Parent (name) {
    this.name = name;
    this.colors = [‘red’, ‘blue’, ‘green’];
}
 
Parent.prototype.getName = function () {
    console.log(this.name)
}
 
function Child (name, age) {
 
    Parent.call(this, name);
    
    this.age = age;
 
}
 
Child.prototype = new Parent();
 
var child1 = new Child(‘kevin’, ’18’);
 
child1.colors.push(‘black’);
 
console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]
 
var child2 = new Child(‘daisy’, ’20’);
 
console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

可取:融入原型链世襲和布局函数的长处,是 JavaScript 中最常用的三番四次情势。

2.1 布局函数形式优化

function Person(name) { this.name = name; this.getName = getName; }
function getName() { console.log(this.name); } var person1 = new
Person(‘kevin’);

1
2
3
4
5
6
7
8
9
10
function Person(name) {
    this.name = name;
    this.getName = getName;
}
 
function getName() {
    console.log(this.name);
}
 
var person1 = new Person(‘kevin’);

可取:消弭了各样方法都要被重新创制的难点

破绽:那叫什么封装……

4.原型式世袭

function createObj(o) { function F(){} F.prototype = o; return new F();
}

1
2
3
4
5
function createObj(o) {
    function F(){}
    F.prototype = o;
    return new F();
}

固然 ES5 Object.create 的效仿完结,将盛传的对象作为创造的指标的原型。

缺点:

带有引用类型的属性值始终都会共享相应的值,那点跟原型链世襲同样。

var person = { name: ‘kevin’, friends: [‘daisy’, ‘kelly’] } var
person1 = createObj(person); var person2 = createObj(person);
person1.name = ‘person1’; console.log(person2.name); // kevin
person1.firends.push(‘taylor’); console.log(person2.friends); //
[“daisy”, “kelly”, “taylor”]

1
2
3
4
5
6
7
8
9
10
11
12
13
var person = {
    name: ‘kevin’,
    friends: [‘daisy’, ‘kelly’]
}
 
var person1 = createObj(person);
var person2 = createObj(person);
 
person1.name = ‘person1’;
console.log(person2.name); // kevin
 
person1.firends.push(‘taylor’);
console.log(person2.friends); // ["daisy", "kelly", "taylor"]

注意:修改person1.name的值,person2.name的值并未有发出改造,实际不是因为person1person2有单独的
name 值,而是因为person1.name = 'person1',给person1增加了 name
值,并不是校订了原型上的 name 值。

3. 原型情势

function Person(name) { } Person.prototype.name = ‘keivn’;
Person.prototype.getName = function () { console.log(this.name); }; var
person1 = new Person();

1
2
3
4
5
6
7
8
9
10
function Person(name) {
 
}
 
Person.prototype.name = ‘keivn’;
Person.prototype.getName = function () {
    console.log(this.name);
};
 
var person1 = new Person();

亮点:方法不会重复创建

症结:1. 有所的性质和方法都分享 2. 不能够初始化参数

5. 寄生式继承

创设叁个仅用于封装世襲进程的函数,该函数在内部以某种格局来做增加对象,最终回来对象。

function createObj (o) { var clone = object.create(o); clone.sayName =
function () { console.log(‘hi’); } return clone; }

1
2
3
4
5
6
7
function createObj (o) {
    var clone = object.create(o);
    clone.sayName = function () {
        console.log(‘hi’);
    }
    return clone;
}

缺欠:跟借用构造函数形式同样,每回创造对象都会创建三遍方法。

3.1 原型模式优化

function Person(name) { } Person.prototype = { name: ‘kevin’, getName:
function () { console.log(this.name); } }; var person1 = new Person();

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name) {
 
}
 
Person.prototype = {
    name: ‘kevin’,
    getName: function () {
        console.log(this.name);
    }
};
 
var person1 = new Person();

可取:封装性好了某个

劣点:重写了原型,错过了constructor属性

6. 寄生组合式世襲

为了方便我们阅读,在那处再度一下组成世襲的代码:

function Parent (name) { this.name = name; this.colors = [‘red’,
‘blue’, ‘green’]; } Parent.prototype.getName = function () {
console.log(this.name) } function Child (name, age) { Parent.call(this,
name); this.age = age; } Child.prototype = new Parent(); var child1 =
new Child(‘kevin’, ’18’); console.log(child1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Parent (name) {
    this.name = name;
    this.colors = [‘red’, ‘blue’, ‘green’];
}
 
Parent.prototype.getName = function () {
    console.log(this.name)
}
 
function Child (name, age) {
    Parent.call(this, name);
    this.age = age;
}
 
Child.prototype = new Parent();
 
var child1 = new Child(‘kevin’, ’18’);
 
console.log(child1)

重新组合世袭最大的瑕疵是会调用若干回父构造函数。

一遍是安装子类型实例的原型的时候:

Child.prototype = new Parent();

1
Child.prototype = new Parent();

二次在创制子类型实例的时候:

var child1 = new Child(‘kevin’, ’18’);

1
var child1 = new Child(‘kevin’, ’18’);

忆起下 new 的模拟达成,其实在此句中,我们会实践:

Parent.call(this, name);

1
Parent.call(this, name);

在那,大家又会调用了贰遍 Parent 布局函数。

据此,在这里个事例中,假如大家打字与印刷 child1 目的,大家会发觉 Child.prototype
和 child1 都有三性格质为colors,属性值为['red', 'blue', 'green']

那么大家该怎么更正,幸免那三次重复调用呢?

假诺大家不使用 Child.prototype = new Parent(卡塔尔 ,而是直接的让
Child.prototype 访问到 Parent.prototype 呢?

拜访如何落实:

function Parent (name) { this.name = name; this.colors = [‘red’,
‘blue’, ‘green’]; } Parent.prototype.getName = function (卡塔尔(英语:State of Qatar) {
console.log(this.name卡塔尔国 } function Child (name, age卡塔尔(英语:State of Qatar) { Parent.call(this,
name卡塔尔(قطر‎; this.age = age; } // 关键的三步 var F = function (卡塔尔(英语:State of Qatar) {};
F.prototype = Parent.prototype; Child.prototype = new F(卡塔尔国; var child1 =
new Child(‘kevin’, ’18’卡塔尔国; console.log(child1卡塔尔国;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Parent (name) {
    this.name = name;
    this.colors = [‘red’, ‘blue’, ‘green’];
}
 
Parent.prototype.getName = function () {
    console.log(this.name)
}
 
function Child (name, age) {
    Parent.call(this, name);
    this.age = age;
}
 
// 关键的三步
var F = function () {};
 
F.prototype = Parent.prototype;
 
Child.prototype = new F();
 
 
var child1 = new Child(‘kevin’, ’18’);
 
console.log(child1);

末尾我们封装一下以此三番五次方法:

function object(o卡塔尔(英语:State of Qatar) { function F(卡塔尔国 {} F.prototype = o; return new F(卡塔尔国; }
function prototype(child, parent卡塔尔 { var prototype =
object(parent.prototype卡塔尔(قطر‎; prototype.constructor = child; child.prototype
= prototype; } // 当我们应用的时候: prototype(Child, Parent卡塔尔;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}
 
function prototype(child, parent) {
    var prototype = object(parent.prototype);
    prototype.constructor = child;
    child.prototype = prototype;
}
 
// 当我们使用的时候:
prototype(Child, Parent);

援用《JavaScript高等程序设计》中对寄生组合式世袭的赞叹正是:

这种艺术的高功用展示它只调用了三遍 Parent 布局函数,况兼由此防止了在
Parent.prototype
上面创设不必要的、多余的习性。与此同时,原型链仍然为能够维系不改变;因而,还能够够通常使用
instanceof 和
isPrototypeOf。开采人士普及以为寄生组合式世袭是援引类型最了不起的袭承范式。

3.2 原型形式优化

function Person(name) { } Person.prototype = { constructor: Person,
name: ‘kevin’, getName: function () { console.log(this.name); } }; var
person1 = new Person();

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name) {
 
}
 
Person.prototype = {
    constructor: Person,
    name: ‘kevin’,
    getName: function () {
        console.log(this.name);
    }
};
 
var person1 = new Person();

可取:实例能够透过constructor属性找到所属布局函数

破绽:原型情势该有的欠缺如故有

深深连串

JavaScript长远种类目录地址:。

JavaScript深远连串猜测写十二篇左右,旨在帮大家捋顺JavaScript底层知识,入眼传授如原型、功效域、推行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、世袭等难题概念。

假定有错误大概不严慎的地点,请必得付与指正,相当多谢。如若合意只怕有所启迪,迎接star,对作者也是黄金年代种鞭挞。

  1. JavaScirpt 浓重之从原型到原型链
  2. JavaScript
    深刻之词法成效域和动态效能域
  3. JavaScript 深刻之实行上下文栈
  4. JavaScript 浓厚之变量对象
  5. JavaScript 深切之效率域链
  6. JavaScript 浓郁之从 ECMAScript 标准解读
    this
  7. JavaScript 深切之实行上下文
  8. JavaScript 深切之闭包
  9. JavaScript 深远之参数按值传递
  10. JavaScript
    深远之call和apply的效仿完成
  11. JavaScript 深切之bind的模仿完成
  12. JavaScript 浓重之new的模拟完毕
  13. JavaScript 深刻之类数组对象与
    arguments
  14. JavaScript
    深切之创设对象的三种办法甚至优劣点

    1 赞 3 收藏
    评论

图片 1

4. 重新组合方式

结构函数形式与原型情势双剑合璧。

function Person(name) { this.name = name; } Person.prototype = {
constructor: Person, getName: function () { console.log(this.name); } };
var person1 = new Person();

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name) {
    this.name = name;
}
 
Person.prototype = {
    constructor: Person,
    getName: function () {
        console.log(this.name);
    }
};
 
var person1 = new Person();

亮点:该分享的分享,该民用的个体,使用最布满的艺术

短处:有的人正是期望任何都写在联合签字,即更好的封装性

4.1 动态原型情势

function Person(name) { this.name = name; if (typeof this.getName !=
“function”) { Person.prototype.getName = function () {
console.log(this.name); } } } var person1 = new Person();

1
2
3
4
5
6
7
8
9
10
function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype.getName = function () {
            console.log(this.name);
        }
    }
}
 
var person1 = new Person();

注意:使用动态原型方式时,不能用对象字面量重写原型

表达下何以:

function Person(name) { this.name = name; if (typeof this.getName !=
“function”卡塔尔国 { Person.prototype = { constructor: Person, getName:
function (卡塔尔(英语:State of Qatar) { console.log(this.name卡塔尔(قطر‎; } } } } var person1 = new
Person(‘kevin’卡塔尔(英语:State of Qatar); var person2 = new Person(‘daisy’卡塔尔(英语:State of Qatar); // 报错 并未该方法
person1.getName(卡塔尔(英语:State of Qatar); // 注释掉上面包车型地铁代码,那句是足以实行的。
person2.getName(卡塔尔(英语:State of Qatar);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype = {
            constructor: Person,
            getName: function () {
                console.log(this.name);
            }
        }
    }
}
 
var person1 = new Person(‘kevin’);
var person2 = new Person(‘daisy’);
 
// 报错 并没有该方法
person1.getName();
 
// 注释掉上面的代码,这句是可以执行的。
person2.getName();

为了批注那么些难题,若是早先推行var person1 = new Person('kevin')

大器晚成旦对 new 和 apply
的底层实践进度不是很精通,能够阅读尾巴部分相关链接中的小说。

我们回看下 new 的落到实处步骤:

  1. 先是新建八个对象
  2. 下一场将对象的原型指向 Person.prototype
  3. 然后 Person.apply(obj)
  4. 归来这一个目的

瞩目此时,回想下 apply 的落实步骤,会奉行 obj.Person
方法,那时就能够奉行 if 语句里的剧情,注意结构函数的 prototype
属性指向了实例的原型,使用字面量情势平昔覆盖
Person.prototype,并不会转移实例的原型的值,person1
长期以来是指向了原先的原型,并不是 Person.prototype。而早先的原型是从未有过
getName 方法的,所以就报错了!

倘使您正是想用字面量方式写代码,能够尝试下这种:

function Person(name) { this.name = name; if (typeof this.getName !=
“function”) { Person.prototype = { constructor: Person, getName:
function () { console.log(this.name); } } return new Person(name); } }
var person1 = new Person(‘kevin’); var person2 = new Person(‘daisy’);
person1.getName(); // kevin person2.getName(); // daisy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype = {
            constructor: Person,
            getName: function () {
                console.log(this.name);
            }
        }
 
        return new Person(name);
    }
}
 
var person1 = new Person(‘kevin’);
var person2 = new Person(‘daisy’);
 
person1.getName(); // kevin
person2.getName();  // daisy

5.1 寄生布局函数方式

function Person(name) { var o = new Object(); o.name = name; o.getName =
function () { console.log(this.name); }; return o; } var person1 = new
Person(‘kevin’); console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object) // true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person(name) {
 
    var o = new Object();
    o.name = name;
    o.getName = function () {
        console.log(this.name);
    };
 
    return o;
 
}
 
var person1 = new Person(‘kevin’);
console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object)  // true

寄生构造函数方式,笔者个人感觉应该如此读:

寄生-构造函数-形式,也便是说寄生在布局函数的风姿罗曼蒂克种方式。

也正是说打着构造函数的招牌名不正言不顺,你看创立的实例使用 instanceof
都没办法儿指向构造函数!

这么方法能够在非正规境况下使用。比方大家想创设三个颇有额外措施的独特数组,不过又不想间接改进Array构造函数,我们得以如此写:

function SpecialArray() { var values = new Array(); for (var i = 0, len
= arguments.length; i len; i++) { values.push(arguments[i]); }
values.toPipedString = function () { return this.join(“|”); }; return
values; } var colors = new SpecialArray(‘red’, ‘blue’, ‘green’); var
colors2 = SpecialArray(‘red2’, ‘blue2’, ‘green2’); console.log(colors);
console.log(colors.toPipedString()); // red|blue|green
console.log(colors2); console.log(colors2.toPipedString()); //
red2|blue2|green2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function SpecialArray() {
    var values = new Array();
 
    for (var i = 0, len = arguments.length; i  len; i++) {
        values.push(arguments[i]);
    }
 
    values.toPipedString = function () {
        return this.join("|");
    };
    return values;
}
 
var colors = new SpecialArray(‘red’, ‘blue’, ‘green’);
var colors2 = SpecialArray(‘red2’, ‘blue2’, ‘green2’);
 
 
console.log(colors);
console.log(colors.toPipedString()); // red|blue|green
 
console.log(colors2);
console.log(colors2.toPipedString()); // red2|blue2|green2

您会发觉,其实所谓的寄生布局函数格局正是比工厂格局在创设对象的时候,多应用了一个new,实际上两个的结果是同等的。

不过小编恐怕是指望能像使用普通 Array 相近采纳 SpecialArray,即使把
SpecialArray 当成函数也长期以来能用,但是那并非小编的本心,也变得不高雅。

在能够应用其余方式的气象下,不要选择这种情势。

可是值得后生可畏提的是,上面例子中的循环:

for (var i = 0, len = arguments.length; i len; i++) {
values.push(arguments[i]); }

1
2
3
for (var i = 0, len = arguments.length; i  len; i++) {
    values.push(arguments[i]);
}

能够替换来:

values.push.apply(values, arguments);

1
values.push.apply(values, arguments);

5.2 安妥构造函数格局

function person(name){ var o = new Object(); o.sayName = function(){
console.log(name); }; return o; } var person1 = person(‘kevin’);
person1.sayName(); // kevin person1.name = “daisy”; person1.sayName();
// kevin console.log(person1.name); // daisy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function person(name){
    var o = new Object();
    o.sayName = function(){
        console.log(name);
    };
    return o;
}
 
var person1 = person(‘kevin’);
 
person1.sayName(); // kevin
 
person1.name = "daisy";
 
person1.sayName(); // kevin
 
console.log(person1.name); // daisy

所谓稳妥对象,指的是从未有过集体性质,而且其艺术也不援用 this 的靶子。

与寄生布局函数情势有两点分化:

  1. 新成立的实例方法不引用 this
  2. 不应用 new 操作符调用结构函数

稳当对象最相符在风流倜傥部分安然还是的意况中。

伏贴布局函数方式也跟工厂形式相像,不能够识别对象所属类型。

深深体系

JavaScript深切体系目录地址:。

JavaScript深远种类预计写十八篇左右,意在帮大家捋顺JavaScript底层知识,注重讲授如原型、成效域、推行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、世襲等苦衷概念。

纵然有错误也许比非常的大心的地方,请务必给与指正,十二分多谢。假设中意照旧有所启示,迎接star,对小编也是意气风发种鞭挞。

  1. JavaScirpt 深远之从原型到原型链
  2. JavaScript
    深远之词法作用域和动态效率域
  3. JavaScript 深切之实行上下文栈
  4. JavaScript 深远之变量对象
  5. JavaScript 深刻之作用域链
  6. JavaScript 深入之从 ECMAScript 标准解读
    this
  7. JavaScript 深入之施行上下文
  8. JavaScript 深远之闭包
  9. JavaScript 深刻之参数按值传递
  10. JavaScript
    深刻之call和apply的比葫芦画瓢达成
  11. JavaScript 浓厚之bind的模拟达成
  12. JavaScript 深远之new的模仿实现
  13. JavaScript 深切之类数组对象与
    arguments

    1 赞 收藏
    评论

图片 1

admin

网站地图xml地图