博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript_面向对象程序设计
阅读量:7064 次
发布时间:2019-06-28

本文共 11336 字,大约阅读时间需要 37 分钟。

类的创建于实例对象

工厂模型创建对象

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(); //zfconsole.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

原型图例:

clipboard.png

console.log(Person.prototype) 的结果:

clipboard.png

常用方法

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 ); //z1console.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的属性中  truevar 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(); //判断是否 一个对象的 原型

clipboard.png

//父类的构造函数  Supfunction Sup ( name ) {        this.name = name;    }//父类的原型对象Sup.prototype = {    constructor: Sup,    sayName: function () {        console.log(this.name);    }}//子类的构造函数 Subfunction 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 );  //zfsub1.sayName();  //zf

原型链继承映射图

clipboard.png


clipboard.png

继承的三种方式

原型继承

//原型继承的特点://即继承了父类的模板,又继承了父类的原型对象。  (全方位的继承)//父类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 ); //zzconsole.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 ); //zfconsole.log( b.age ); //20console.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 );//z1console.log( b.sex ); //女console.log( b.id ); //10b.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;  //还原父类原型对象的构造器            }    }

转载地址:http://qjill.baihongyu.com/

你可能感兴趣的文章
第十五周学习进度条
查看>>
3G美餐:谁有红苹果?
查看>>
ASP.NET中Html.Partial和Html.Action的一个区别
查看>>
VMM系列之添加Hyper-V群集主机到VMM服务器
查看>>
Java开源报表JasperReport、iReport4.5.1使用详解(二)
查看>>
使用必应查询接口开发搜索工具:反查一个IP上的旁站
查看>>
RHCE 学习笔记(7) 进程管理
查看>>
Lync Server 2010迁移至Lync Server 2013故障排错 Part 2: Lync Server 迁移后部分用户无法移池问题...
查看>>
Hyper-V 2节点集群高可用的限制
查看>>
Silverlight Navigation导航框架实例系列汇总
查看>>
走近复杂数据库计算型软件的设计与制作(3)—视图的设计
查看>>
域用户权限|运行软件
查看>>
如何解决双显示器显示B/S架构软件的问题
查看>>
Android笔记:Wake Lock
查看>>
简单易用的headless浏览器
查看>>
编写shell脚本的另一种方法
查看>>
产品设计体会(2012)另一种产品版本细分策略
查看>>
企业WIFI安全应用方案
查看>>
修改eclipse自动生成的comments中的author名字
查看>>
路由基础概念解析
查看>>