js中面向对象(建立对象的几种方式)

 

一、面向对象编程(OOP)的特色javascript

  抽象:抓住核心问题html

  封装:只能经过对象来访问方法java

  继承:从已有的对象下继承出新的对象编程

  多态:多对象的不一样形态windows

 注:本文引用于 http://www.cnblogs.com/yuxingyoucan/p/5797142.html数组


 

1、建立对象的几种方式app

javascript 建立对象简单的来讲,无非就是使用内置对象或各类自定义对象,固然还可使用JSON,但写法有不少,也能混合使用。函数

一、工厂方式建立对象:面向对象中的封装函数(内置对象)性能

function createPerson(name){
   //一、原料
    var obj=new Object();
   //二、加工
    obj.name=name;
    obj.showName=function(){
       alert(this.name);
    }     
    //三、出场
     return obj; 
} 
var p1=createPerson('小米');
p1.showName();

与系统对象的区别:this

    var arr=new Array();//生成一个系统数组对象

    一、系统对象是直接用 new 在外面生成,而工厂定义的是在函数内部生成

    二、工厂定义的函数名称第一个是小写开头,而系统定义的是大写开头

工厂模式的优缺点:虽然解决了建立类似对象的问题,可是却没有解决对象识别问题(即怎样知道一个对象的类型)。

二、构造函数建立对象

  当new去调用一个函数,这个时候函数中的this就是建立出来的对象,并且函数的返回值就是this(隐式返回)

  new后面的函数叫作构造函数

  <1>有参数的构造函数

function CreatePerson(name){
  this.name=name;
  this.showName=function(){
    alert(this.name);
  }
}
    var p1=new CreatePerson('小米');

  <2>无参数的构造函数

  function CreatePerson(){}
    var p1=new CreatePerson();
    p1.name="小米";
    p1.showName=function(){
     alert(p1.name);
    }
    p1.showName();

构造函数模式的优缺点:

  一、优势:建立自定义函数意味着未来能够将它的实例标识为一种特定的类型,这是构造函数赛过工厂模式的地方

  二、缺点:每一个方法都要在每一个实例上从新建立一遍

三、对象字面量方式建立对象

person={
  name:"小米",
  age:23
};

四、用原型方式 

  一、原型对象:只要建立了一个新函数,就会为该函数建立一个prototype属性,这个属性指向函数的原型对象。在默认状况下,全部的原型对象都会自动得到一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针

  二、能够经过isPrototypeOf()方法来肯定对象之间是否存在这种关系

function Person(){}
Person.prototype.name="小米";
Person.prototype.showName=function(){
alert(this.name);
}
var p1=new Person();
p1.showName();

原型模式的优缺点:

  一、优势:可让全部的对象实例共享它所包含的属性和方法

  二、缺点:原型中是全部属性都是共享的,可是实例通常都是要有本身的单独属性的。因此通常不多单独使用原型模式。

5.混合模型

  构造函数模式定义实例属性,而原型模式用于定义方法和共享的属性

function CreatePerson(name){
  this.name=name;
}
  Create.prototype.showName=function(){
    alert(this.name);
  }
    var p1=new CreatePerson('小米');
    p1.showName();
   var p2=new CreatePerson('小米');
    p2.showName();
  alert(p1.showName==p2.showName);//true;缘由:都是在原型下面,在内存中只存在一份,地址相同

  总结:

  function 构造函数(){

    this.属性;

  }

  构造函数.原型.方法=function(){};

  var 对象1=new 构造函数();

  对象1.方法();

 


 

原型:去改写对象下面公用的的方法或属性,让公用的方法或属性在内存中存在一份(提升性能)

原型:prototype:要写在构造函数的下面

var  arr=[];
arr.number=10;
Array.prototype.number=20;
alert(arr.number);//10,
//缘由:普通定义的要比原型定义的权重大,先会找自身的,自身没有的话再沿着原型链找原型上是否有

属性是否要放在原型下面,就要看该属性是不是可变的,若是不是可变的,就能够放在原型下面,用来公用属性,可变的话放在构造函数下面。

 


 

this的指向问题:在事件或者定时器下比较容易出问题

 


 

 2、包装对象

一、咱们把系统自带的对象,叫作系统对象。例如:Array,Date

二、包装对象:基本类型都有本身对应的包装对象:String,Number,Boolean

  var str='hello';//基本类型:字符串类型

  str.charAt(0);//基本类型会找到对应的包装对象类型,而后包装对象把全部的属性和方法给了基本类型,而后包装对象消失。

  str.number=10;//在包装对象下创一个对象,将属性建立在对象下面,而后包装对象就消失了,

  alert(str.number);//会弹出undefined;缘由:会在包装对象下从新建立一个对象

 


 

3、原型链

  原型链:实例对象与原型之间的链接,叫作原型链  

  _proto_(隐式链接)

   Object对象类型是原型链的最外层

  

  实例对象->先查找本身自己下面的属性和方法->自身没找到会沿着原型链找到该对象的原型,再查看原型上是否有要查找的属性或方法->依次继续查找若是找到的话则返回,不然找到最顶层Object上尚未就真没有了

 


 

4、面向对象中的属性和方法 

 一、hasOwnProperty():看是否为对象自身下面的属性和方法

  只有对象本身定义的属性和方法则返回true,若是在prototype下定义发属性和方法为公用的,因此返回为false;

二、constructor:查看对象的构造函数

  (能够用来检测函数类型例如检测是不是数组)

  每一个原型函数都会自动添加constructor属性(只会生成这一个属性)

  for in的时候有些属性是找不到的(系统自带的属性是for in找不到的,本身定义的能够找到)

  避免修改constructor属性

function Aaa(){}
//Aaa.prototype.name='小米';
//Aaa.prototype.age=6;
//alert(a1.constructor);//Aaa 缘由:只是给原型添加了属性,并非从新赋值了,自动添加的constructor属性还在。
Aaa.prototype={
//  constructor:'Aaa',//须要手动修正指向问题
  name:'小米',
  age:6
}
var a1=new Aaa();
alert(a1.constructor);//Object 缘由:将原型的prototype从新赋值了,但里面没有constructor

 注意:以这种方式重设constructor属性会使它的[Enumerable]特性被设置为true,默认状况下,原生的constructor属性是不可枚举的。能够经过Object.defineProperty()来修改。

三、instanceof:运算符

  对象与构造函数在原型链上是否有关系,也能够用做类型判断但不是最好的方案,最好的方案是用toString 方法来判断。

四、toString():object上的方法,把对象转化为字符串

var arr=[];
alert(arr.toString==Object.prototype.toString);//false
//缘由:系统对象下面都是自带的(例如数组的toString在Array.prototype下),本身写的对象都是经过原型链找到object下面的toString
function Aaa(){}
var a1=new Aaa();
alert(a1.toString==Object.prototype.toString);//true

1>利用toString 进制转化

 Number.toString(进制);

var num=255;
alert(num.toString(16));//ff---转化为16进制,默认不写转化为十进制

2>利用toString作类型判断:

  //跨页面的状况下上面两种状况会失效

 var oF=document.createElement('iframe');

  document.body.appendChild('oF');

  var ifArray=windows.frames[0].Array;//iframe下的Array数组

  var arr=new ifArray();

  alert(arr.constructor==Array);//false

  alert(arr instanceof Array);//false

  alert(Object.prototype.toString.call(arr)=='[object Array]');//true

 

var arr=[];
alert(Object.prototype.toString.call(arr));//[Object Array] 
var arr={};
alert(Object.prototype.toString.call(arr));//[Object Object] 
var arr=new Date;
alert(Object.prototype.toString.call(arr));//[Object Date] 
var arr=new RegExp;
alert(Object.prototype.toString.call(arr));//[Object RegExp]  
var arr=null;
alert(Object.prototype.toString.call(arr));//[Object Null] 

 


 

 

五 、继承

一、继承方式:

  一、拷贝继承:通用型  有new无new均可以用

  二、类式继承:new构造函数---利用构造函数(类)继承的方式

  三、原型继承:无new的对象---借助原型来实现对象继承对象

  属性继承:调用父类的构造函数call

  方法继承:用for in的形式 拷贝继承(jq也用拷贝继承)

        var a = {
            name: '小米'
        };
        //拷贝继承
        function extend(obj1, obj2) {
            for (var attr in obj2) {
                obj1[attr] = obj2[attr];
            }
        }
        //原型继承
            var b=cloneObj(a);
            b.name='小乔';
            alert(a.name);
            alert(b.name);
            function cloneObj(obj) {
                var F=function () {};
                F.prototype=obj;
                return new F();
            }
        //类式继承
        function A() {//父类
            this.name='小米';
        }
        A.prototype.showName=function () {
            alert(this.name);
        }
        function B() {//子类
            A.call(this);//属性和方法分开继承
        }    //B.prototype=new A();//一句话实现继承,但会有不少问题,好比指向问题,属性会互相影响    //类式继承改进:至少由如下四句实现方法的继承,属性须要分开继承
        var F=function () {};
        F.prototype=A.prototype;
        B.prototype=new F();
        B.prototype.constructor=A;//修正指向问题
        var b1=new B();
        b1.name='笑笑';
        b1.showName();
相关文章
相关标签/搜索