JavaScript_面向对象程序设计

类的建立于实例对象

工场模子建立对象

function CreatePerson ( name,sex,age ) {
    
    var obj = new Object();
    
    obj.name = name;
    obj.sex = sex;
    obj.age = age;
    
    obj.sayName = function () {
        
        console.log( this.name );
        
    }
    
    return obj;
    
}

var p1 = CreatePerson('zf','女',22);

p1.sayName(); //zf

console.log( p1.name );  //zf

组织函数式

//函数的第一个字母大写(类的模板)
function Person ( name,age,sex ) {
    
    this.name = name;
    this.age = age;
    this.sex =sex;
    
    this.sayName = function () {
        
        alert(this.name);
        
    }
    
}

//组织一个对象,  运用new关键字, 通报参数,   实行模板代码, 返回对象。

var p1 = new Person('zf',20,'女');  //类的观点:依据模板建立出差别的实例对象
 
console.log( p1.name );

p1.sayName();

建立类的实例:

  • 看成组织函数去运用

    var p1 = new Person(‘a1’,20);

  • 作为一般函数去挪用

    Person(‘a2’,20); //在全局环境中定义属性并赋值, 直接定义在window上。

  • 在另个一对象的作用域中挪用

    var o = new Object();
    Person.call(o,’a3′,23);

Object每一个实例都邑具有的属性和要领:

Constructor: 保留着用于建立当前对象的函数。(组织函数)
hasOwnProperty(propertyName):用于检测给定的属性在当前对象实例中(而不是原型中)是不是存在。
isPrototypeOf(Object): 用于搜检传入的对象是不是是别的一个对象的原型。
propertyIsEnumerable(propertyName):用于搜检给定的属性是不是能够运用for-in语句来罗列。
toLocaleString():返回对象的字符串示意。该字符串与实行环境的区域对应.
toString():返回对象的字符串示意。
valueOf():返回对象的字符串、数值或布尔示意。

推断一个对象是不是是另一个对象的实例,一般运用的是 instanceof. 比较少运用constructor。

原型

建立每一个函数的时刻,都有一个prototype属性. 这个是属性,是一个指针。而这个对象老是指向一个对象。
这个对象 的用处就是将特定的属性和要领包括在内,是一个实例对象, 起到了一个一切实例所同享的作用。
屏障了,组织函数的瑕玷,new 一个对象,就把组织函数内的要领实例化一次。

function Person () {
                
}

var obj = Person.prototype;

console.log( obj );  //Person.prototype 就是一个对象
//Person.prototype 内部存在指针,指针指向一个对象。 这个对象称之为:原型对象。原型对象,被一切的实例对象所同享。

console.log( obj.constructor ); //function Person(){}  //obj这个对象的组织器就是 Person

原型图例:

《JavaScript_面向对象程序设计》

console.log(Person.prototype) 的效果:
《JavaScript_面向对象程序设计》

经常使用要领

Object.getPrototypeOf()

依据实例对象取得原型对象

每次代码读取一个对象的属性的时刻:首先会举行一次搜刮,搜刮实例对象里,看看是不是存在,假如没有,再去实例所对的原型中寻觅属性.假如有则返回,假如两次都没有则返回undefined

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}

var p1 = new Person();

console.log( p1.name ); //z1

console.log( Object.getPrototypeOf(p1) );  
console.log( Object.getPrototypeOf(p1) == Person.prototype ); //true

hasOwnProperty()

推断是不是是 实例对象本身的属性

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}


// 推断一个对象属性 是属于 原型属性 照样属性 实例属性

var p3 = new Person();    
console.log( p3.name ); //zf 是原型上的

//hasOwnProperty() 是不是是 实例对象本身的属性 
console.log( p3.hasOwnProperty('name') ); //false 

in 操作符

无论是 原型的属性, 照样实例对象的属性, 都辨别不开。 假如存在,返回true

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}


//推断属性是不是存在 实例对象 和 原型对象中. 

var p1 = new Person();
console.log('name' in p1); //true  //示意,name的属性究竟在不在p1的属性中  true
var p2 = new Person();

p1.name = 'zzz';

console.log('name' in p1); //true

推断一个属性是不是在原型中

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}


//推断属性是不是存在 实例对象 和 原型对象中. 

var p1 = new Person();
p1.name = '123';

//在原型对象中,是不是存在这个值
//@obj 当前对象
//@推断的属性
function hasPrototypeProtoperty ( obj,attrName ) {
    
    return !obj.hasOwnProperty(attrName) && (attrName in obj);
    
}

console.log( hasPrototypeProtoperty(p1,'name') );  //false

Object.keys()

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}

//ECMA5新特征  Object.keys(); 
//拿到当前对象中的一切keys, 返回一个数组

var p1 = new Person();
p1.name = 'zz';
p1.age = 20;

var attr = Object.keys(p1);
console.log( attr );  //["name", "age"]

var attr2 = Object.keys(p1.__proto__);  

console.log( attr2 );  //["name", "age", "sayName"]

var attr3 = Object.keys(Person.prototype);  

console.log( attr3 );  //["name", "age", "sayName"]

Object.getOwnPropertyNames()

function Person () {
}

Person.prototype.name = 'z1';
Person.prototype.age = 20;

Person.prototype.sayName = function () {
    
    console.log( '我是原型对象要领' );
    
}

var p1 = new Person();
p1.name = 'zz';
p1.age = 20;

//ECMA5 
//constructor属性,是没法被罗列的. 一般的for-in轮回是没法罗列. [eable = false];

//Object.getOwnPropertyNames(); //罗列对象一切的属性:不论该内部属性能够被罗列.

var attr4 = Object.getOwnPropertyNames(Person.prototype); //["constructor", "name", "age", "sayName"]

console.log( attr3 );

isPrototypeOf()

推断原型的要领

原型对象.isPrototypeOf(new instance);

完成each要领

原型的别的一个作用就是扩大对象中的属性和要领


//遍历多维数组
var arr = [1,2,4,5,[455,[456,[345345]]]];


Array.prototype.each = function ( cb ) {

    try {

        //计数器
        this.i || (this.i = 0);

        //中心代码
        if ( this.length > 0 && cb.constructor === Function ) {

            while ( this.i < this.length ) {  //计数器 大于 数组长度跳出

                //取得每一项值    
                var e = this[this.i];

                //推断是不是是 数组
                if ( e && e.constructor === Array ) {

                    //递归
                    e.each(cb);

                } else {

                    cb.call(null,e);

                }

                this.i++;    

            }

            //运用完以后,开释变量
            this.i = null;

        }


    } catch (e) {
        //do someting
        
    }

    return this;

};


arr.each(function( val ){

    console.log(val);

});

简朴原型

直接经由过程对象字面量来重写全部原型对象(这类要领会转变原型对象的组织器[转变成Object])

//简朴原型
            
function Person () {
    
}

Person.prototype = {
    
    constructor: Person,  //原型的组织器转变
    
    name: 'zz',
    age: 20,
    
    say: function () {
        console.log( this.age );
    }
    
}

var p1 = new Person();

console.log( p1.name );
p1.say();

存在的题目,constructor属性是没法被罗列的。加在原型对象上,能够被罗列,被罗列。不符合请求。

ECMA5中的Object.defineProperty()要领能够为原型对象从新加入组织器。constructor题目能够被防备。

//3个参数,  参数1:从新设置组织的对象 (给什么对象设置)     参数2:设置什么属性        参数3:options设置项 (要怎样去设置)
Object.defineProperty(Person.prototype,'constructor',{
    enumerable: false,  //是不是是 能够 被罗列
    value: Person  //值   组织器的 援用
});

原型的动态特征

注重原型和建立实例的前后递次

function Person () {
                        
}

var p1 = new Person();  // {}
 
Person.prototype = {
    constructor: Person,
    name: 'zf',
    age: 20,
    say: function () {
        console.log('原型');
    }
}

//先把原型对象写好,然后再实例化。

//p1.say();    //error 由于      原型对象内里没有任何属性和要领

var p2 = new Person();

p2.say();

//注重  简朴原型运用的递次(实例对象必须在原型对象以后建立)

原型对象的经常使用开辟形式

组合组织函数式和原型形式

function Person( name,age,firends ) {
    
    this.name = name;
    this.age = age;
    this.firends = firends;
    
}

Person.prototype = {
    constructor: Person,
    sayName: function () {
        console.log( this.name );
    }
}

var p1 = new Person('zz',20,['zf']);
var p2 = new Person('zx',22,['z1']);

console.log( p1.firends ); //['zf']                
console.log( p2.firends );  //['z1']

动态原型形式

就是把信息都封装到函数中,如许表现了封装的观点。

//动态原型形式:(让你的代码  都封装到一同)
function Person( name,age,firends ) {
    
    this.name = name;
    this.age = age;
    this.firends = firends;
    
    //动态原型要领
    if ( typeof this.sayName !== 'function'  ) {
        
        Person.prototype.sayName = function () {
            console.log(this.name);
        }
        
    }
    
}

稳妥组织函数式

稳妥形式就是没有大众属性,而且其他要领也不援用this对象,稳妥形式最合适在平安的环境中运用。假如顺序关于平安性请求很高,那末异常合适这类形式。
也不能运用new关键字。

//稳妥组织函数式  durable object (稳妥对象)
//1,没有大众的属性
//2,不能运用this对象

function Person ( name,age ) {
    
    //建立一个要返回的对象。  应用工场形式头脑。
    var obj = new Object();
    
    //能够定义一下是有的变量和函数 private
    
    var name = name || 'zf';
    
//                        var sex = '女';
//                        var sayName = function () {
//                        }

        
    //增加一个对外的要领
    obj.sayName = function () {
        console.log(name);
    }
    
    return obj;
    
}

var p1 = Person('xixi',20);

p1.sayName();    

深切原型继续的观点

假如让原型对象即是另一个范例的实例,效果会怎样呢?明显此时的原型对象将包括一个指向另一个原型的指针,响应的另一个原型中也包括着一个指向另一个组织函数的指针。

原型链: 应用原型让一个援用范例继续别的一个援用范例的属性和要领。

组织函数 原型对象 实例对象

  • 组织函数.prototype = 原型对象

  • 原型对象.constructor = 组织函数

  • 实例对象.__proto__ = 原型对象

  • 原型对象.isPrototypeOf(实例对象)

  • 组织函数 实例对象 (类和实例)

isPrototypeOf(); //推断是不是 一个对象的 原型

《JavaScript_面向对象程序设计》

//父类的组织函数  Sup
function Sup ( name ) {
    
    this.name = name;
    
}

//父类的原型对象
Sup.prototype = {
    constructor: Sup,
    sayName: function () {
        console.log(this.name);
    }
}

//子类的组织函数 Sub
function Sub ( age ) {
    
    this.age = age;
    
}

//假如子类的原型对象  即是 父类的 实例

//1, 明显此时的原型对象将包括一个指向另一个原型的指针
//2, 响应的另一个原型中也包括着一个指向另一个组织函数的指针。

//            实例对象.__proto__ = 原型对象
//                Sup的实例对象  和 Sup的原型对象 有一个关联

Sub.prototype = new Sup('zf');

//            console.log( Sub.prototype.constructor );  //function Sup () {}
//            
//            console.log( Sub.prototype.__proto__ );    //Sup 的 原型对象


var sub1 = new Sub(20);

console.log( sub1.name );  //zf
sub1.sayName();  //zf

原型链继续映照图

《JavaScript_面向对象程序设计》

《JavaScript_面向对象程序设计》

继续的三种体式格局

原型继续

//原型继续的特性:
//即继续了父类的模板,又继续了父类的原型对象。  (全方位的继续)
//父类
function Person ( name,age ) {
    
    this.name = name;
    this.age = age;
    
}

Person.prototype.id = 10;

//子类
function Boy ( sex ) {
    
    this.sex = sex;     
    
}

//原型继续
Boy.prototype = new Person('zz');

var b = new Boy();

console.log( b.name ); //zz
console.log( b.id ); //10

类继续

类继续 (只继续模板) 不继续原型对象 (借用组织函数的体式格局继续)

//父类
function Person ( name,age ) {
    
    this.name = name;
    this.age = age;
    
}

Person.prototype.id = 10;

//子类
function Boy ( name,age,sex ) {
    
    //类继续
    Person.call(this,name,age);
    
    this.sex = sex;     
    
}

var b = new Boy('zf',20,'女');

console.log( b.name ); //zf
console.log( b.age ); //20
console.log( b.sex );  //女
console.log( b.id );  //父类的原型对象并没有继续过来.

    

夹杂继续

原型继续+类继续

    
    //父类     (关联父类和子类的关联)
function Person ( name,age ) {
    
    this.name = name;
    this.age = age;
    
}

Person.prototype.id = 10;
Person.prototype.sayName = function () {
    console.log( this.name );
}

//子类
function Boy ( name,age,sex ) {
    
    //1 类继续
    Person.call(this,name,age);   //继续父类的模板
    
    this.sex = sex;     
    
}                

//2 原型继续
//父类的实例  和 父类的 原型对象的关联.
Boy.prototype = new Person();   //继续父类的原型对象

var b = new Boy('z1',20,'女');

console.log( b.name );//z1
console.log( b.sex ); //女
console.log( b.id ); //10

b.sayName(); //z1    

ExtJs底层继续体式格局

模仿ExtJs底层继续一部分代码

//ExtJs  继续
//2件事: 继续了1次父类的模板,继续了一次父类的原型对象


function Person ( name,age ) {
    
    this.name = name;
    this.age = age;
    
}

Person.prototype = {
    
    constructor: Person,
    
    sayHello: function () {

        console.log('hello world!');

    }
    
}

function Boy ( name,age,sex ) {
    
    //call 绑定父类的模板函数  完成  借用组织函数继续  只复制了父类的模板
    
//                Person.call(this,name,age);

        Boy.superClass.constructor.call(this,name,age);
    
    this.sex = sex;        
    
}

//原型继续的体式格局: 即继续了父类的模板,又继续了父类的原型对象。
//            Boy.prototype = new Person();
//只继续 父类的原型对象
    extend(Boy,Person);  // 目标 只继续 父类的原型对象  , 须要那两个类发生关联关联.

//给子类加了一个原型对象的要领。
Boy.prototype.sayHello = function () {
    
    console.log('hi,js');
    
}

var b = new Boy('zf',20,'男');

console.log( b.name );
console.log( b.sex );
b.sayHello(); 

Boy.superClass.sayHello.call(b);

//extend要领

//sub子类, sup 父类
function extend ( sub,sup ) {
    
    //目标, 完成只继续 父类的原型对象。   从原型对象入手
    
    //1,建立一个空函数, 目标:空函数举行中转
    var F = new Function();  // 用一个空函数举行中转。
    
//                把父类的模板屏障掉, 父类的原型取到。
    
    F.prototype = sup.prototype;  //2完成空函数的原型对象 和 超类的原型对象转换
    
    sub.prototype = new F();  //3原型继续
    
    //做善后处理。 复原组织器 ,
    sub.prototype.constructor = sub;  //4 ,复原子类的组织器
    
//                保留一下父类的原型对象  // 由于 ①轻易解耦, 减低耦合性      ② 能够轻易取得父类的原型对象
    sub.superClass = sup.prototype;   //5 ,保留父类的原型对象。   //自定义一个子类的静态属性   , 接收父类的原型对象。
    
    //推断父类的原型对象的组织器, (防备简朴原型中给更改成  Object)
    if ( sup.prototype.constructor == Object.prototype.constructor ) {
        
        sup.prototype.constructor = sup;  //复原父类原型对象的组织器
        
    }
    
}

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