实例可以识别为一个特定的类型,相当于重写了
分类:巴黎人-前端

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 () { console.log(this.name); } } } } var person1 = new Person('kevin'); var person2 = new Person('daisy'); // 报错 并未该措施 person1.getName(); // 注释掉下边包车型地铁代码,那句是足以施行的。 person2.getName();

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

            }

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 中最常用的三回九转方式。

JavaScript承继格局总括

承继:超类构造函数中有品质有法子,超类原型中有总体性有办法,子类想要承袭超类的构造函数,超类原型中的部分属性和艺术,于是便有了持续。

  • 原型链承继:讲多少个品类的实例赋值给另一个构造函数的原型,子类型就可见访谈超类型全数的属性和艺术
//原型链的继承
//缺点:对象实例共享所有的属性和方法,因此不适合单独使用。
function Parent(){
    this.name="mike";
}
function Child(){
    this.age=19;
}
Child.prototype=new Parent();//子类原型等于父类实例
var test =new Child();
console.log(test.age);
console.log(test.name);

function Brother(){
    this.weight=60;
}
Brother.prototype=new Child();
var brother=new Brother();
console.log(brother.name);
console.log(brother.age);```

- 借用构造函数模式

//借用构造函数/类式承袭call()/apply()
//能够传递参数,不过方法不或者共享
function Parent(age){
this.name=['mike','jack','smith'];
this.age=age;
}
function Child(age){
Parent.call(this,age);
}
var test=new Child(21);
console.log(test.age);//21
console.log(test.name);//mike,jack,smith
test.name.push('bill');
console.log(test.name);//mike,jack,smith,bill

//call()和apply()用法分别
The difference is that apply lets you invoke the function with arguments as an array;
call requires the parameters be listed explicitly.
A useful mnemonic is "A for array and C for comma(逗号)."```

  • 组合式继承:原型链和构造函数结合的不二诀要,原型链承接分享的性质和措施,构造函数承接实例属性。
//组合式继承
//组合构造函数和原型链
//原型链继承原型属性和方法,构造函数实现实例属性的继承
function Parent(name){
    this.name=name;
    this.arr=['aaa','bbb','ccc'];
}

Parent.prototype.run=function(){
    return this.name;
};

function Child(name,age){
    Parent.call(this,age);//第二次调用
    this.age=age;
}

Child.prototype=new Parent();//第一次调用```

- 原型式继承:不必预先定义构造函数的情况下实现继承,本质是执行给定对象的浅复制,而复制的副本还可以得到进一步的改造。

//借助于原型并依靠已有个别对象创制新指标,同时还不用创立自定义类型
function obj(o){
function F(){}
F.prototype=o;
return new F();
}
var box={
name:"masike",
arr:['baba','mama','didi']
};
var b1=obj(box);
console.log(b1.name);//masike

b1.name='mike';
console.log(b1,name);//mike

console.log(b1,arr);//baba,mama,didi
b1.arr.push("parents");
console.log(b1.arr);//baba,mama,didi,parents

var b2=obj(box);
console.log(b2.name);//masike
console.log(b2.arr);//baba,mama.didi,parents

- 寄生式继承:基于某个对象后某些信息创建一个对象,然后增强对象,最后返回对象。

function create(o){
var f=obj(o);
f.run=function(){
return this.arr;
}
return f;
}```

  • 寄生组合式承袭:集寄生式承袭和组合是再而三优点于一身,是达成基于项目继承的最实用的情势。化解组合承接格局由于每每调用父类构造函数而变成低效用难点。
//寄生组合式类型
//解决了父类构造函数两次调用问题
function obj(o){  //(原型式)
    function F(){}
    F.prototype=o;
    return new F();
}
function create(parent,test){
    var f=obj(parent.prototype);//创建对象
    f.constructor=test;//增强对象
}
function Parent(name){
    this.name=name;
    this.arr=['brother','sister','parents'];
}

Parent.prototype.run=function(){
    return this.name;
}
function Child(name,age){
    Parent.call(this,name);
    this.age=age;
}
Child.prototype = obj(Parent.prototype);//实现继承

var test=new Child("masike",19);
test.arr.push("withershins");
console.log(test.arr);
console.log(test.run());//只共享了方法

var test2=new Child("jack",22);
console.log(test2.arr);//引用问题解决```

未完待续......
>继承最推荐的解决方案:

         if(!Object.create){//object.create()是ES5新增方法
                Object.create= (function(){
                    function F(){}   //创建中介函数(bridge)
                    return function(obj) {
                        if(arguments.length !== 1) {
                            throw new Error("仅支持一个参数");
                        }
                        F.prototype = obj;   //原形绑定
                        return new F();      //返回实例
                    }
                })()
        //最终返回的结果,既是F的实例属性,享有F构造函数中的所有属性和方法(因为F构造函数为空,所以完全不用担心会有多余不想要的属性方法存在),[[prototype]]又指向F.prototype,返回的结果是一个对象!!!
        }
        function Person(name, age) {
                this.name = name;
                this.age = age;
        }
        Person.prototype.walk = function() {//写到了prototype中,walk一定是想要共享的方法
                console.log("走路....");
        } 
        function Child(name, age, address) {
                Person.call(this, name, age);//这里继承了person构造函数中想要传递的一些属性
                this.address = address;
        }
        Child.prototype = Object.create(Person.prototype);//不要再使用new了!
        Child.prototype.talk = function() {
            console.log("说话ing.....")
        }
        //不用new的原因是因为你不想要Child继承Person构造函数中的所有属性和方法,而是想让他单独继承Person.prototype中共享的属性和方法。```

 

深远体系

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

新创造的实例方法不援引 this

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

缺点:

措施都在构造函数中定义,每一回创立实例都会创设一回方法。

JavaScript创制对象方式总计

  • object构造函数、对象字面量
//object构造函数
// 优点:简单方便
// 缺点:批量创建对象很麻烦,不能使用instanceof来确定对象类型
var person = new Object();
person.name = "masike";
person.age=19;
person.job="student";
person.sayName=function(){
    console.log(this.name);
};

//字面量
var person = {
    name:"masike",
    age:22,
    job:"student",
    sayName:function(){
        console.log(this.name);
    }
}```
- 工厂模式:简单的函数创建对象,为对象添加属性和方法,然后返回对象,这个模式后来被构造函数所取代。
```JavaScript
//工厂模式
// 优点:减少了代码量
// 缺点:未能解决对象识别问题
function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=19;
    o.job="student";
    o.sayName=function(){
        console.log(this.name);
    }
    return o;
}
var person1=createPerson("masike",19,"student");
var person2=createPerson("withershins",20,"worker");```
- 构造函数模式:自定义引用类型,像创建对象实例一样使用new操作符,缺点是每个成员无法得到复用,包括函数。

//构造函数情势
//优点:在工厂方式的底子下化解了目的记别难题
//弱点:每种实例的艺术都以单独的,多数场地下同个对象的实例方法都以同等的
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
var person1=new Person("masike",19,"student");
var person2=new Person("withershins",19,"worker");
//偏方
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=sayName;
}
function sayName(){
console.log(this.name);
}
var person1=new Person("masike",19,"student");
var person2=new Person("withershins",19,"worker");```

  • 原型方式:使用prototype属性分享属性和措施。
//原型模式
//优点:公用原型减少了赘余
//缺点:在原型的改变会影响到所有的实例,于是实例没有了独立性
function Person(){
}
Person.prototype.name="masike";
Person.prototype.age=19;
Person.prototype.job="student";
Person.prototype.sayName=function(){
    console.log(this.name);
}
var person1=new Person();
person1.sayName();
var person2=new Person();
person2.sayName();
console.log(person1.sayName==person2.sayName);```
- 组合使用构造函数模式和原型模式:构造函数定义实例属性,原型定义共享的属性和方法。

//组合使用构造函数和原型格局
//优点:结合了构造函数和原型情势的长处,并缓和了毛病
//劣点:代码未有被很好地包裹起来
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=student;
this.friends=["num1","num2"];
}
Person.prototype={
constructor:Person,
sayName:function(){
console.log(this.name);
}
}
var person1=new Person("masike",19,"student");
var person2=new Person("withershins",19,"worker");
person1.friends.push("vash");
console.log(person1.friends);
console.log(person2.friends);
console.log(person1.friends===person2.friends);
console.log(person1.sayName===person2.sayName);```

图片 2

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);

    if (typeof this.getName != "function") {

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传参

JavaScript创建对象方法计算精粹博文
javascript承袭讲授优秀博文
于江水 承继疏解

  这种方式开创的指标与构造函数可能构造函数的原型属性之间一向不涉嫌,不能够注重instanceof 来明显指标类型。建议能够在动用任何情势的情形下毫不采纳这种情势。

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. 无法初叶化参数

然后 Person.apply(obj)

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;
}

缺陷:跟借用构造函数情势一样,每趟成立对象都会创建三次方法。

(1)第一种
function Newperson(){
    
}

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
  14. JavaScript 深入之创立对象的种种办法以及优劣势

    1 赞 3 收藏 评论

图片 3

Newperson.prototype.name = 'tom';
Newperson.prototype.age = 22;
Newperson.prototype.job = 'teacher';
Newperson.prototype.sayName = function(){
    alert(this.name);
}

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属性找到所属构造函数

症结:原型形式该有的欠缺照旧有

    var o = new Object();

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 值。

console.log(friend.constructor);//Person()
console.log(person.constructor);//Object()

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();

亮点:该分享的分享,该民用的私有,使用最广大的措施

劣势:有的人正是愿意一切都写在协同,即越来越好的封装性

能够替换到:

写在前头

正文讲解JavaScript种种承袭形式和优弱点。

而是注意:

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

var person1 = new Newperson();

JavaScript 深远之创立对象的各个方法以及优劣点

2017/05/28 · JavaScript · 对象

原稿出处: 冴羽   

};

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 () { 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);

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) { 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。开垦职员广泛以为寄生组合式承继是引用类型最出彩的后续范式。

var person = new Person();

写在前边

那篇作品批注创设对象的各样方法,以及优短处。

然而注意:

这篇小说更像是笔记,因为《JavaScript高档程序设计》写得真是太好了!

var person1 = new Person();

JavaScript 深切之继续的有余措施和优弱点

2017/05/28 · JavaScript · 继承

原稿出处: 冴羽   

function Person(){
    
}

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');

亮点:化解了每个方法都要被再一次创制的主题材料

症结:那叫什么封装……

    this.getName = getName;

console.log(person2.constructor);//Newperson()

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属性

person1.sayName(); // kevin

1、原型方式创制对象

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');

症结:对象不恐怕辨别,因为具备的实例都针对多个原型

// 报错 并未该办法

console.log(person1.constructor);//Newperson()

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');

优点:实例能够分辨为叁个一定的门类

弱点:每一遍创造实例时,每一个方法都要被创设叁次

    o.getName = function () {

var friend = new Person();

    };

 2、寄生构造函数情势创立对象
    //eg1
    function Animal(name, age, voice){
        var o = new Object();
        o.name = name;
        o.age = age;
        o.voice = voice;
        o.sayVoice = function(){
            return this.voice;
        }
        return o;
    }
    
    var cat = new Animal('喵咪', 2, 'miao');
    console.log(cat.name);//喵咪
    console.log(cat.sayVoice());//miao
    
    //eg2
    function Specialarray(){
        var values = new Array();
        values.push.apply(values, arguments);
        values.toPipedString = function(){
            return this.join('|');
        }
        return values;
    }
    
    var array1 = new Specialarray('a', 'b', 'c');
    console.log(array1.toPipedString());//a|b|c
    console.log(array1.constructor);//Array()
    console.log(array1 instanceof Object);//true

}

//用贰个蕴涵全部属性和艺术的指标字面量重写原型对象,也正是重写了Newperson的prototype对象
Person.prototype = {
        //constructor:Person,//增加那句,能够使 person.constructor 指向 Person
        name:'tom',
        age:22,
        job:'teacher',
        sayName:function(){
            alert(this.name);
        }
}

            }

var person2 = new Newperson();

}

(2)第二种

    }

    getName: function () {

  1. 原型形式

        Person.prototype = {

var person2 = new Person('daisy');

        Person.prototype = {

console.log(colors2.toPipedString()); // red2|blue2|green2

var person1 = new Person();

    return values;

person1.sayName(); // kevin

}

        console.log(this.name);

    o.getName = function () {

var colors = new SpecialArray('red', 'blue', 'green');

var person1 = person('kevin');

}

function getName() {

            console.log(this.name);

    };

优点:该分享的分享,该民用的私有,使用最常见的措施

        return new Person(name);

伏贴对象最适合在一部分安然无事的条件中。

person1.getName(); // kevin

本文由巴黎人手机版发布于巴黎人-前端,转载请注明出处:实例可以识别为一个特定的类型,相当于重写了

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文