面向对象与原型

创建对象并且给对象添加属性和方法

全局函数不需要加分号,但是如果是函数内部又声明了一个 函数,那么 这个函数就要加分号

工厂模式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>工厂模式</title>
    <script type = "text/javascript">
        /*
            创建一个方法,内部创建了一个对象,根据方法传入的参数,给函数的属性赋值
            函数执行后返回这个对象给调用者,这样调用者就是达到了这个对象,

            好处:如果要多次创建这个类型的对象,使用这种方法,可以减少重复的显示书写创建
                  效率高,
            缺点:因为都是通过这个方法创建的对象,所以不好区分
        */
        function creat(name,age){ 
            var box = new Object();
            box.name = name;
            box.age = age;
            box.run = function(){
                return this.name+this.age;
            };
            return box;
        }

        var a = creat("xiaoming",23);//返回一个符合要求的对象
        var b = creat("xaohua",33);

        alert(a.run());
        alert(b.run());
    </script>
</head>
<body>

</body>
</html>

构造函数

所有的构造函数都是Object

构造函数后台会new Object

没有返回语句,后台自动返回

构造函数也是函数,但是第一个字母必须大写,

必须是new 构造函数创建对象

浏览器会根据函数名首字母是不是大写,来判断是不是构造函数,只有构造函数才符合上述规则。

  • 构造函数与普通函数的区别:
    1. 构造函数的首字母必须大写,系统会根据首字母是不是大写来判断这个
      函数是不是一个构造函数
    2. 构造函数和普通函数一样,也可以传入参数
    3. 构造函数不需要返回值,因为系统会默认返回,但是普通函数
      必须显示使用return 返回,否则函数没有返回值
    4. 构造函数用来创建对象的,使用new + 构造函数名(参数列表)
  • 构造函数和工厂模式的区别

    1. 工厂模式可以一份代码创建多个实例,但是多个实例之间并不容易
      区分他们的引用类型,因为他们的类型都是一样的
    2. 构造函数创建对象,不容的构造函数创建的对象是不一样的,这样
      多个实例之间容易区分,但是代码书写的要比较多
function Box(name,age){
            this.name = name;
            this.age = age ;
            this.run = function(){
                return this.name + this.age;
            };
        }

        var a = new Box("nihao",33);
        var b = new Box("haha",3);

        alert(a.run());
        alert(b.run());

原型

  • hasOwnPropetry()
    • 判断一个属性是不是对象中存在的,如果是那么返回true,如果不是返回false,false的情况可能是是原型的属性,或者不存在

      function Person(){
      this.name = "小明";
      this.age = 33;
      }
      Person.prototype.gender = "男";
      var a = new Person();
      //判断对象a中是否存在age属性
      alert(a.hasOwnProperty("age"));//对象中存在的属性true
      alert(a.hasOwnProperty("gender"));//对象中不存在,原型中存在的属性false
      alert(a.hasOwnProperty("ssss"));//对象和原型都不存在的属性 false
  • in 判断某一个属性是否存在一个对象和原型中,先查找对象中的,在查找原型中的,只要存在返回true.
function Person(){
        this.name = "小明";
        this.age = 33;
        }
    Person.prototype.gender = "男";
    var a = new Person();
    /*
    //判断对象a中是否存在age属性
    alert(a.hasOwnProperty("age"));//对象中存在的属性true
    alert(a.hasOwnProperty("gender"));//对象中不存在,原型中存在的属性false
    alert(a.hasOwnProperty("ssss"));//对象和原型都不存在的属性 false
    */
    alert("name" in a);//true
    alert("gender" in a);//true
    alert("xxx" in a);//false
  • 引申
    • 判断一个属性是不是对象的方法
      • 先用in 判断是对象或者原型的
      • 再次用hasOwnProperty()判断是对象的,还是原型的。
  • 原型的写法

    • 和构造函数相似,函数名首字母大写
    • 多了原型属性和原型方法,格式:
    • 构造函数名+prototype+属性名/方法名 = 初始化
  • 实例属性和原型属性的访问规则

    • 如果有实例属性优先访问实例属性
    • 如果没有实例属性,那么访问原型属性
    • 例子如下,访问实例属性,结果是shili,访问原型属性结果是hah
          function Box(){
              this.name = "shilishuxing";
          };//花括号内的属性是实例属性
          Box.prototype.name = "haha"; //这些事原型属性
          Box.prototype.age = 23;
          Box.prototype.run = function(){
              return "is running";
          }
      
          var a = new Box();
          alert(a.name);//优先访问实例属性,如果没有实例属性,那么访问原型属性
  • 创建了多个原型对象,他们的原型属性和原型方法都是相同的
  • 原型的属性和方法也是可以被覆盖的,如下:
function Box(){};
Box.prototype.name = "haha";

var a = new Box();
a.name = "234";
alert(a.name);
  • 上面的式子结果是234,因为程序遵循就近原则

constructor

  • constructor 存在于原型对象中,他指向了构造函数,
  • 访问方法 Person.prototype.constructor
  • 如果修改了原型中的属性constructor,那么将不在相等
function Person(){
            this.age = 34;

            Person.prototype.sex = "男";

        }
    //修改Person原型的对象字面量,不指向了Person的原型对象,那么它的属性constructor将不再是Person函数
    Person.prototype ={
            name:'dfsdf',
            age:29,


        };


    var a = new Person();
    alert(Person.prototype.constructor === Person);//false

Prototype 和 proto

  • prototype是函数的内置属性,这个熟悉的值可以被多个对象共享
  • proto是对象的内置属性,这个属性指向构造函数的属性prototype

    • 着两个prototype 和 proto是完全相同的

          p.__proto__ ===Person.prototype
      
          结果是true
  • 当一个对象访问一个他的属性的时候,会首先从自定义的属性开始查看,如果没有查找它的proto属性
    function Person(){

        this.age = 22;

    }
    Person.prototype.name="小明"var a = new Person();
    alert(a.name);

  • 实例分析:
    • 创建对象调用了构造函数,函数内的原型属性prototype也是一个对象,他有一个属性,name的值是xiaoming ,
    • 创建了 一个对象a,那么对象的内置属性proto指向了prototype
    • 当访问name属性的时候,虽然a对象没有定义,但是它的原型中有name属性,这样就可以访问到

创建对象的模式

  • 组合模式:构造函数封装属性,原型封装方法
<script type="text/javascript">
    //在构造方法内部封装属性
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    //在原型对象内封装方法
    Person.prototype.eat = function (food) {
        alert(this.name + "爱吃" + food);
    }
    Person.prototype.play = function (playName) {
        alert(this.name + "爱玩" + playName);
    }

    var p1 = new Person("李四", 20);
    var p2 = new Person("张三", 30);
    p1.eat("苹果");
    p2.eat("香蕉");
    p1.play("志玲");
    p2.play("凤姐");
</script>
  • 动态原型模式
<script type="text/javascript">
    //构造方法内部封装属性
    function Person(name, age) {
        //每个对象都添加自己的属性
        this.name = name;
        this.age = age;
        /*
            判断this.eat这个属性是不是function,如果不是function则证明是第一次创建对象,
            则把这个funcion添加到原型中。
            如果是function,则代表原型中已经有了这个方法,则不需要再添加。
            perfect!完美解决了性能和代码的封装问题。
        */
        if(typeof this.eat !== "function"){
            Person.prototype.eat = function () {
                alert(this.name + " 在吃");
            }
        }
    }
    var p1 = new Person("志玲", 40);
    p1.eat();   
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值