码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript 随笔2 面向对象 原型链 继承

时间:2016-07-17 21:07:57      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

第六章 面向对象的程序设计

1、创建对象的几种方式

 A)工厂模式

   function CreatObj(name,sex,age){

     this.name=name;

     this.sex=sex;

     this.age=age;

}

 缺点:虽然可以批量创建对象,却不能知道对象的类型 只知道他是Object类型;

B)构造函数

 

 

  function Person(name,sex){

     this.name=name;

     this.sex=sex;

     this.sayName=function(){

      alert(this.name);

}

}

 

function Person(name,sex){

      this.name=name;

      this.sex=sex;

this.sayName=sayName;

}

function sayName(){

alert(this.name);

}

 

优点:每个实例都有自己的实例属性,并且共享同一个方法

缺点:第一种方式函数没有复用,第二种方法是在全局作用域中的,如果方法过多对象就毫无封装性可言了

C)原型模型

 function Person(){};

 Person.prototype={

constructor:PerSon,

name:”hanyakui”,

age:26,

friends:[“bushi”,”jack”,”lusy”]

}

优点:解决了对象的方法复用问题

缺点:所有实例共享同一原型属性,不同实例都可以修改同一个引用类型的属性 如friends;

      所有实例的属性都是一样的,都叫hanyakui 26岁

D) 组合使用构造函数和原型模型

   function Person(name,sex,friends){

        this.name=name;

        this.sex=sex;

        this.friends=friends;

    }

    Person.prototype={

        constructor:Person,

        country:"china",

        sayName:function (){

            alert(this.name);

        }

    }

    var person1 = new Person("hanyakui", "男", ["tom", "jack"]);

    var person2 = new Person("hanyakui222", "男22", ["2222", "22222"]);

person2.friends.push("newadd");

优点:每个实例都有自己的实例属性(包括引用类型),同时又共享原型中的属性和方法;

这是使用最多的创建自定义类型(对象)的方式。

 

2、原型链

  原型链的基本思想:让一个引用类型继承另一个引用类型的属性和方法,及让一个引用类型的原型(prototype)指向另一个引用类型的构造函数。

 

3、如何实现自定义引用类型的继承

 

A)利用原型链实现继承

 

//父类

  function Person(){

    this.name=”hanyakui”;

    this.friend=["tom", "jack"];

};

  Person.prototye.sayName=function(){

    alert(this.name);

}

 

 

 

 

 

 // 子类

function ChinaPerson(){};

ChinaPerson.prototype=new Person();

 

var instance1=new ChinaPerson();

alert(instance2.friends);// tom,jack

 

var instance2=new ChinaPerson();

instance2.friends.push(“newadd_friend”);

 

alert(instance2.friends);// tom,jack,newadd_friend

alert(instance1.friends);// tom,jack,newadd_friend

 

缺点:所有子类的实例都用于共同的属性和方法,尤其是引用类型属性会被所有实例共享,一个实例修改 别的实例属性就会发生变化,如上面friends

 

B)利用构造函数实现继承(经典继承)

function Person(name,friends){

        this.name=name;

        this.friends=friends;

        this.sex=”男”;

        this.sayName=function(){ alert(this.name)};

    }

 

    function ChinaPerson(){

        Person.apply(this,arguments)

    }

 

    var instance1=new ChinaPerson("hanyakui",["tom","jack"]);

    var instance2=new ChinaPerson("hanyakui22",["tom22","jack22"]);

优点:继承了父类属性,同时传递了参数,从而保证子类每个实例有不同的实例属性

缺点:和使用构造函数声明对象一样 方法没复用或没有封装性

 

   C)组合使用构造函数和原型实现继承(伪经典继承

思路:利用原型链实现对原型属性和方法的继承,利用构造函数实现实例属性的继承。

//父类

function Person(name ,friends){

   this.name=name;

   this.friends=friends;

}

Person.prototype.sayName=function(){

    alert(this.name);

}

//子类

function ChinaPerson(){

this.country=”中国”;

Person.apply(this,arguments);    //继承实例属性

}

ChinaPerson.prototype=new Person(); //继承原型属性和方法

ChinaPerson.prototype.constructor=ChinaPerson;

 

ChinaPerson.prototype.sayFreinds=function(){

 alert(this.freinds);

}

 

tip:这是最常用的继承方式、不要在父类原型中使用引用类型属性,因为所以子类实例都可以修改。

 

   D)其他继承方式  原型式继承、寄生式继承、寄生组合式继承

第七章 函数表达式 闭包的实现

1、函数表达式

  var doSomething=function(){

    //do Something

};

2、闭包 (在函数内部使用匿名函数 就会构成闭包)

var objectArr=[{age:200,name=”张三”},{age:100,name:”李四”}];

function compareobject(age){

 return function(obj1,obj2){

 var age1=obj1.age;

var age2=obj2.age;

if(age 1< age 2) return -1;

    else if(age 1> age 2) return 1;

else return 0;

};  //返回一个 闭包 ,闭包引用age;

}

objectArr.sort(compareobject(“age”)); 

3、变量对象 和 作用域链 (理解闭包很重要)

  每个函数都有自己的执行环境,每个执行环境中都有一个表示变量的对象----变量对象作用域链本质上是一个指向 变量对象 的一个指针列表,它只引用但不实际包含变量对象。

4、闭包与变量

 

function createFunction_1() {

        var results = new Array();

        for (var i = 0; i < 10; i++) {

            results[i] = function () {return i;};

        }

        return results;

    }

    var arr = createFunction_1();

alert(arr[0]());//10

results;//[ function () {return i;},…….]

function createFunction_2(){

  var result=new Array();

  for (var i=0;i<100;i++){

  result[i]=function (num){

return function(){return num; }

}(i);

}

return result;

}

result;//[ function (num) { },…….]

 

createFunction_1: 函数内部的匿名函数构成了闭包,闭包的作用域链包含包含函数createFunction_1的变量对象i的引用,故函数执行完毕后,result的值都是100;

createFunction_2: 在闭包之外套接了一个带参数的匿名函数,由于函数参数数按照值传递的,故闭包获得的不是i的引用,而是num的值。

//疑惑

改动createFunction_1():利用了块级作用域

results[i] = (function () { return i; })();

//result值为 [0,1,2,3….9]

改动createFunction_2():

result[i] = (function (num) {return function () { return num; }}(i))();

 

5、模仿块级作用域

  (function(){

     //这里是一个块级作用域 也称私有作用域,外围无法直接访问其中的变量(可通过特权方法访问)

})();   //( ... )();

块级作用域:通过定义并立即调用一个匿名函数,实现块级作用域。 将函数声明包含在一对圆括号内,表示他实际上是一个函数表达式。而紧随其后的一对圆括号表示立即执行这个函数表达式。

(function createFunction_2() {

        alert("将函数声明转为函数表达式,并立即调用!");

})();

//将函数声明转为函数表达式,并立即调用!

给一个函数声明套上()函数声明就变成了函数表达式。改动createFunction_1()中将匿名函数声明改为了函数表达式并立即调用了该函数,匿名函数立即执行了,因此返回了正确的值。

6、私有变量(构造函数)

function MyObject(){

   //私有变量和私有函数

   var privateVariable=10;//是变量不是属性 Name:100

   function privateFunction(){

     return false;

   }

 

  //定义特权方法 公开私有变量和私有函数

   this.publicMethod=function(){

 privateVariable++;

 return privateFunction();

}

}

缺点:在构造函数中定义特权方法。每个实例都换创建同样的一组方法 老毛病了 见前面

7、静态私有变量(原型)

(function(){

  //私有变量和私有函数

   var privateVariable=10;//是变量不是属性 Name:100

   function privateFunction(){

     return false;

   }

  // 构造函数 不使用var 关键字 声明的是全局变量

  MyObject=function(){

   //这是一个全局变量

};

 

//特权方法

MyObject.prototype.publicMethod=function(){

privateVariable++;

 return privateFunction();

};

})();

优点&缺点: 私有变量和函数是所有实例共享的。

 

JavaScript 随笔2 面向对象 原型链 继承

标签:

原文地址:http://www.cnblogs.com/hanyakui/p/5679271.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!