美文网首页程序员
JS 面向对象与原型(一)

JS 面向对象与原型(一)

作者: sky丶星如雨 | 来源:发表于2018-03-07 11:34 被阅读0次

    面向对象的语言有一个标志,就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象,而ECMAScript中没有类的概念。

    ECMA-262 把对象定义为 :“无序属性的集合,其属性可以包含基本值,对象或函数。” 严格来说,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。想象成,一组名值对,值可以是数据或函数。

    创建对象:
    方法一: 一次只能创建一个对象,当想创建另一个属性方法相同的对象时,会产生大量重复性的代码。

            var box = new Object();
            box.name = "Lee";
            box.age = 100;
            box.run = function () {
                return this.name + this.age + "运行中...";
            }
            alert(box.run());
            alert(this.name);
    
    

    方法二:
    工厂模式:解决了实例化对象产生大量重复的问题,但,存在识别问题,即,无法识别box1,box2 到底属于哪个对象的实例。

    
      function createObject(name, age) {  // 集中实例化的函数
            var obj = new Object();  // 创建对象
            obj.name = name;         // 添加属性
            obj.age = age;           // 添加属性
            obj.run = function () {  // 添加方法
                return this.name + this.age + "运行中...";
            }
            return obj;               // 返回对象引用
        }
    
        var box1 = createObject("Qiqi", 29);  // 创建第一个对象
        var box2 = createObject("tianyu", 25);// 创建第二个对象
        alert(box1.run());               // 打印第一个对象的run()
        alert(box2.run());               // 打印第二个对象的run()
    

    方法三:
    构造函数方式 : 既解决了重复实例化的问题,又解决了对象识别的问题

       function Box(name, age) {       // 创建一个对象,所有构造函数的对象就是Object
            this.name = name;           // 添加一个属性
            this.age = age;
            this.run = function () {    // 添加一个方法
                return this.name + this.age + "运行中...";
            };
        }
    
       function Desk(name, age) {       // 创建一个对象,所有构造函数的对象就是Object
            this.name = name;           // 添加一个属性
            this.age = age;
            this.run = function () {    // 添加一个方法
                return this.name + this.age + "运行中...";
            };
        }
        var box1 = new Box("Lee", 100);  // 实例化
        var box2 = new Box("Jack", 200); // 实例化
        var box3 = new Desk("KKK",300); // 实例化
    
        alert(box1.run());
        alert(box2.run());
    
        alert(box1 instanceof Box);  // true;
        alert(box2 instanceof Box);  // true;
        // 对比可知,box3 是属于 Desk 的对象的引用,而不是 Box , 解决了识别问题
        alert(box3 instanceof Desk); // true;
        alert(box3 instanceof Box);   // false   
    

    构造函数方式与工厂模式的不同之处:

    1. 构造函数没有 new Object , 但它后台会自动创建,并传给一个对象 var obj = new Object();
    2. this 就相当于 obj
    3. 构造函数不需要返回对象引用,后台自动返回

    构造函数规范:

    1. 构造函数也是函数,但函数名第一个字母大写
    2. 必须 new 构造函数名(), new Box(), 而这个 Box 第一个字母也是大写的
    3. 必须使用 new 运算符

    调用构造函数实际经历的过程:

    1. 创建一个新对象
    2. 将构造函数的作用域赋给这个新对象(因此,this就指向了这个新对象)
    3. 执行构造函数中的代码
    4. 返回新对象
        var o = new Object();
        Box.call(o, "abc", 10);
        alert(o.run());
    

    也可以使用call()或apply() 在某个特殊对象的作用域中调用Box()函数。这里是在对象o的作用域中调用的,因此,调用后o就拥有了所有属性和run()方法

    再来看一个问题:

       function Box(name, age) {
            this.name = name;
            this.age = age;
    //        this.run = function () {
    //            return this.name + this.age + "运行中...";
    //        }
            this.run = new Function("return this.name + this.age + '运行中...'");
        }
    
    
        var box1 = new Box("Lee", 100);
        var box2 = new Box("Lee", 100);
        alert(box1.run()); // 正常执行
        alert(box1.run() == box2.run()); // true  方法的值相等
        alert(box1.run == box2.run);     // false  引用地址不同
    

    以上代码可以看出,也可以使用 new Function() 的方法来代替 ,说明了 run() 是引用类型,值相等,而引用地址不等,说明值存储在堆内存中,引用地址存储在栈内存中,具有唯一性。

    相关文章

      网友评论

        本文标题:JS 面向对象与原型(一)

        本文链接:https://www.haomeiwen.com/subject/kundfftx.html