JavaScript继续的头脑完成

JavaScript作为一门语法比较松懈的言语,在ES6之前并没有像C++/Java等传统OO言语一样有class关键字,也不能经由过程private,public等关键字来限制权限。本篇就引见一下JavaScript是怎样完成继续的(js的继续说白了只是一种头脑上的继续,在代码级别并没有像java的自然继续,在编写js的时刻采纳oo头脑,能更简朴的优化和扩大代码)。

JavaScript的继续能够分为两类:
• 基于对象的继续
• 基于范例的继续

基于对象的继续
基于对象的继续也叫原型继续。我们晓得经由过程JavaScript字面量建立的对象都邑连接到Object.prototype,因而我们用Object.prototype来完成继续。本质上是摒弃类,不挪用组织函数,而是用Object.create(),直接让新对象继续旧对象的属性。比方:

var person = {
    name: "Jack",
    getName: function () { return this.name; }
}
var p1 = Object.create(person);
console.log(p1.getName());    //Jack

代码很简朴,person有一个属性和一个要领。对象p1经由过程Object.create()来继续,第一个参数prototype指向person的prototype,如许对象p1就继续了person的属性和要领。
Object.create()还能够指定第二个参数,即数据属性,将其添加到新对象中。数据属性可设4个描述符value, writable,enumerable,configurable 。后3个看名字也能猜出意义,不指定的话默以为false。由于和本篇关系不大,就不跑题了,只看看设置value的状况:

var p2 = Object.create(person, {
    name: {
        value: "Zhang"
    }
});
console.log(p2.getName());    //Zhang

用Object.create()相当于建立了一个全新的对象,你能够给该对象恣意新增,重载它的属性和要领:

var person = {
    name: "Jack",
    getName: function () { return this.name; },
    getAge: function() { return this.age; } //注重并没有age这个成员变量,依靠子类完成
}

var p3 = Object.create(person);
p3.name = 'Rose';
p3.age = 17;
p3.location = '上海';
p3.getLocation = function() { return this.location; }

console.log(p3.getName());    //Rose
console.log(p3.getAge());     //17
console.log(p3.getLocation());    //上海

在person中并没有age这个属性,因而你挪用person.getAge();将获得undefined。但在对象p3里新定义了age这个属性,因而就可以正确地挪用基类的getAge要领。别的子类重载了name的值,且新定义了location属性和getLocation要领。结果如上所示,不赘述。

基于范例的继续
基于范例的继续是经由过程组织函数依靠于原型的继续,而非依靠于对象。比方:

function Person(name) {
    this.name = name;
    this.getName = function () { return this.name; };  
}
function Student(name, age) {
    Person.call(this, name);
    this.age = age;
    this.getAge = function () { return this.age; }; 
}
Student.prototype = new Person();    //须要经由过程new来接见基类的组织函数

var p = new Person('Cathy');
var s = new Student('Bill', 23);

console.log(p.getName());    //Cathy
console.log(s.getName());    //Bill
console.log(s.getAge());     //23

Student继续自Person。name虽然是在基类Person里被定义的,但用new挪用Person的组织函数后,this将被绑定到子类Student对象上,因而name最终是定义在子类Student对象上的。结果如上所示,不赘述。
庇护隐私
之所以定义getName,getAge等要领就是不想让用户直接接见name,age等属性。惋惜上面两种继续均没法庇护隐私,都可像p.name,p.age如许直接接见属性。假如以为这些属性的隐私异常重要,愿望模拟出OO言语中private属性的结果,能够用函数模块化。
所谓函数模块化,本质上就是在函数内新建一个对象,新对象的要领里运用参数对象的属性,然后将新对象返回。此时新对象里是没有参数对象的属性的,达到了庇护隐私的目标。代码以下:

var person = function(spec) {
    var that = {};        //新对象
    that.getName = function () { return spec.name; };  //运用参数的属性
    that.getAge = function() { return spec.age; };  //运用参数的属性
    return that;        //返回新对象
}

var p4 = person({name: 'Jane', age: 20});

console.log(p4.name);    //undefined
console.log(p4.age);     //undefined
console.log(p4.getName());    //Jane
console.log(p4.getAge());     //20

由于函数person返回的是新对象that,而that里并没有name和age属性,因而直接接见会获得undefined。只能经由过程that暴露出的两个接口来猎取name和age。
进一步完成多层继续也异常轻易,结果以下,不赘述:

var student = function(spec) {
    var that = person(spec);        //新对象继续自person
    that.getRole = function() { return 'student'; };  //新对象增添要领
    that.getInfo = function() {
        return spec.name + ' ' + spec.age + ' ' + that.getRole();
    };
    return that;    //返回新对象
};

var p5 = student({name:'Andy', age:12});

console.log(p5.name);       //undefined
console.log(p5.getName());  //Andy
console.log(p5.getRole());  //student
console.log(p5.getInfo());  //Andy 12 student

更多资本上:去转盘;或许加我的QQ群介入js,css的议论进修(QQ群:512245829)

    原文作者:痞子猫
    原文地址: https://segmentfault.com/a/1190000006701256
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞