JS原型及面对对象总结

1、对象

ECMAScript有两种开发模式:1.函数式(过程化)2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象,而ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。那如何在JS中实现面对对象编程呢?实际上,JS语言是通过一种叫做 原型(prototype的方式来实现面向对象编程的。

  • 创建对象

 在JS里面创建对象有3种方式:

1、子面量

语法:var  对象名={属性,方法};

实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>创建学生对象</title>
</head>
<body>
<script>
     var student = {
         name:"张三",
         sex:"男",
         age:18,
         sayHi:function () {
             alert("大家好,我是"+this.name+",性别:"+this.sex+",今年"+this.age+"岁");
         }
     }
     student.sayHi();
</script>
</body>
</html>

缺陷:它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的,(每个实例对象没有自己的特性)

解决方式:初始化的值都一直每个实例对象没有自己的特性,伪类可以解决问题,
使用组合(构造函数+原型模式)解决传参合共享的问题。

2、调用系统的构造函数创建对象

语法:var 对象名=new Object();

实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>创建学生对象</title>
</head>
<body>
<script>
    var student = new Object();
    student.name="张三";   //属性
    student.sex="男";
    student.age=18;
    student.sayHi=function () {
        alert("大家好,我是"+this.name+",性别:"+this.sex+",今年"+this.age+"岁");
    }

    student.sayHi();
</script>
</body>
</html>

缺陷:上面创建了一个对象,并且创建属性和方法,在sayHi()方法里的 this,就是代表 student对象

本身。这种是 JS创建对象最基本的方法,但有个缺点,想创建一个类似的对象,就会产生大量的代码。

解决方式:使用工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题。

解决例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>工厂方法</title>
</head>
<body>
<script>
    //创建对象的方法
    function createStudent(name,sex,age) {
        var student = new Object();
        student.name =name;
        student.sex=sex;
        student.age =age;
        student.sayHi=function () {
            alert("大家好,我是"+this.name+",性别:"+this.sex+",今年"+this.age+"岁");
        }
        return student;
    }

    var person1 =createStudent("张三","男","18");
    person1.sayHi();
    var person2 = createStudent("李四","女","20");
    person2.sayHi();
</script>
</body>
</html>

3、自定义构造函数方式创建对象:

语法:function 对象名(属性....);

实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>构造函数</title>
</head>
<body>
<script>
    /*
    构造函数也是函数,函数名首字母大写,主要用于创建对象。
    经历的步骤:
    1.创建一个对象
    2.将构造函数的作用域给到新的对象
    3.执行构造函数代码
    4.返回对象
    * */
    function Student(name,sex,age) {
        this.name=name;
        this.sex=sex;
        this.age=age;
        this.sayHi=function () {
            alert("大家好,我是"+this.name+",性别:"+this.sex+",今年"+this.age+"岁");
        }
    }

    var student1 = new Student("张三","男","18");
    student1.sayHi(); 
  
    //constructor构造器 instanof
    alert(student1.constructor==Student);
    alert("instanceof Student:"+(student1 instanceof Student) );//测试是不是指向Student
    alert("instanceof Object:"+(student1 instanceof Object) );//测试是不是指向Object
</script>
</body>
</html>

缺陷:每次创建一个Student, 都给我创建了一个sayHi()的实例。 同一个功能的方法,有着多个相同实例

解决方式:原型方法 

2、原型

我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype 通过调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所包含的属性和方法 。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中 。

实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原型</title>
</head>
<body>
<script>
    /*
    *   在javascript中,每一个函数都有一个prototype属性 ,prototype是一个指针,指向对象。
    * */
    function Student() {//创建构造函数

    }
    Student.prototype.name ="张三";//在原型里添加属性
    Student.prototype.sex="男";
    Student.prototype.age="19";
    Student.prototype.sayHi=function () {//在原型里添加方法
        alert("大家好,我是"+this.name+",性别:"+this.sex+",今年"+this.age+"岁");
    }

    var student1 = new Student();//实例化对象
    student1.sayHi();
    var student2 = new Student();
    student2.sayHi();
    

</script>
</body>
</html>

2.1构造函数的和原型模式的关系如图:



2.2原型-继承

在JS中实现继承利用原型链的关系去实现继承的。每个函数都有一个原型对象,每一个实例对象都有指针指向原型。

原型链: 实例与原型的链条。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原型链</title>
</head>
<body>
<script>
  
    function Humans() {
        this.foot=2;
    }
    Humans.prototype.getFoot=function () {
        return this.foot;
    }

    function Man() {

    }
    Man.prototype = new Humans(); //改变原型指向(继承Humans对象)

    var man1 = new Man();
    alert(man1.getFoot());
    alert(man1 instanceof Humans);
</script>
</body>
</html>

原型链问题 如下实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原型链</title>
</head>
<body>
<script>
    function Humans() {
         this.name="张三";
         this.fruit=["香蕉","苹果","梨"];
    }
    function Man() {

    }
    Man.prototype = new Humans(); //继承Humans

    var man1 = new Man();
    man1.fruit.push("火龙果");
    alert(man1.fruit);

    var man2 = new Man();
    alert(man2.fruit);

    /*
    问题1:引用类型,原型属性被所有的实例对象共享了。
    问题2:创建子类的时候 不能给父类传参数了。
    * */

</script>
</body>
</html>

解决方式:使用借用构造函数继承 如下解决实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>借用构造函数</title>
</head>
<body>
<script>
    //问题1:引用类型,原型属性被所有的实例对象共享了。
    //解决问题1
    function Humans() {
         this.name="张三";
         this.fruit=["香蕉","苹果","梨"];
    }
    function Man() {
        Humans.call(this);  //把this 替换为 Humans对象。   让每一个Man对象都拥有一个独立的fruit空间。
    }
   // Man.prototype = new Humans(); //继承Humans

    var man1 = new Man();
    man1.fruit.push("火龙果");
    alert(man1.fruit);

    var man2 = new Man();
    alert(man2.fruit);

</script>
</body>
</html>

图中 call方法可以 把this 替换为 Humans对象 如果Humans对象有参数 也可以 把 Humans对象 参数传递过来,

语法:对象.call(this,参数......);

优点:解决了属性继承,并且值不重复的问题。

缺陷:父级类别中的方法不能继承。

解决方法:组合继承 : 组合继承就是  原型继承+借用继承。

实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组合继承</title>
</head>
<body>
<script>
    function Humans(name) {
         this.name=name;
         this.fruit=["香蕉","苹果","梨"];
    }
    Humans.prototype.getName=function () {
        return this.name;
    }
    function Man(name) {
        //继承Humas ,同时传递了一个name参数
        Humans.call(this,name);  //继承属性
        this.head=1;
    }
    Man.prototype = new Humans(); //继承方法
    Man.prototype.getHead=function () {
        return this.head;
    }

    var man1 = new Man("李四");
    man1.fruit.push("火龙果");
    alert(man1.fruit);
    alert(man1.getName());
    alert(man1.getHead());

    var man2 = new Man("王五");
    alert(man2.fruit);
    alert(man2.getName());
    alert(man2.getHead());
</script>
</body>
</html>








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值