美文网首页
6_2 创建对象

6_2 创建对象

作者: 诺诺诺诺Daddy | 来源:发表于2019-08-27 15:37 被阅读0次
        // 虽然构造函数和对象字面量都可以用来创建对象,但这些方式都有一个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码.为解决这个问题,人们开始使用工厂模式的一种变体。
        //工厂模式
        // 优点:解决了创建多个相似对象的问题,
        // 缺点:没有解决对象识别的问题(即怎样知道一个对象的类型)
        function createPerson(name,age,job){
            var o = new Object();
            o.name = name;
            o.age = age;
            o.job = job;
            o.sayName = function(){
                alert(o.name);
            };
            return o;
        }
        var person1 = createPerson('jerry',20,'honker');
        // person1.sayName();//jerry
        // console.log(typeof person1);//object
        console.log(person1 instanceof createPerson);
        
        
        //构造函数模式
        // ECMAScript中构造函数可以创建特定类型的对象,像object和Array这样的原生构造函数,在运行时会自动出现在执行环境中.从而定义自定义对象类型的属性和方法
        //要创建新实例,必须使用 new 操作符
        //缺点:就是每个方法都要在每个实例上重新创建一遍
        function Person(name,age,job){//按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头;为了区别于 ECMAScript 中的其他函数
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayName = function(){
                alert(this.name);
            }
        };
        var person1 = new Person("Nicholas", 29, "Software Engineer");
        var person2 = new Person("Greg", 27, "Doctor");
        //person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor (构造函数)属性,该属性指向 Person
        //以这种方式定义的构造函数是定义在 Global 对象(在浏览器中是 window 对象)中的
        console.log(person1)
        console.log(person1.constructor == Person);//实例的constructor属性指向Person构造函数
        console.log(person1 instanceof Person);//检测对象类型
        
        
        //构造函数和其他函数的唯一区别就是调用的方式不同,构造函数也是函数,任何函数通过new来定义,那么他都可以称为构造函数
        var person = new Person("Nicholas", 29, "Software Engineer");//当做构造函数来使用
        // person.sayName(); //"Nicholas"
        
        Person("Greg", 27, "Doctor");//添加到window // 作为普通函数调用
        // window.sayName();//"Greg"
        
        var o = new Object();// 在另一个对象的作用域中调用
        Person.call(o,"Kristen", 25, "Nurse");
        // o.sayName();
        
        
        
        //原型模式
        // 创建的每一个函数都有一个prototype属性,这个属性是一个指针, 指向一个对象,而这个对象的作用是包含可以由特定类型的所有实例共享的属性和方法;
        function Person(){};//构造函数为空, 方法和所有属性直接添加到了 Person 的 prototype 属性中
        Person.prototype.name = "Nicholas";
        Person.prototype.age = 23;
        Person.prototype.job = "hunter";
        Person.prototype.sayName = function(){
            alert(this.name);
        }
        var person1 = new Person();
        // person1.sayName();//Nicholas
        var person2 = new Person();
        // person2.sayName();//Nicholas
        // alert(person1.sayName == person2.sayName) // true 新对象的这些属性和方法是由所有实例共享的
        console.log(Person);//ƒ Person(){} 构造函数
        console.log(Person.prototype);//{name: "Nicholas", age: 23, job: "hunter", sayName: ƒ, constructor: ƒ} 构造函数的原型对象
        console.log(Person.prototype.constructor);//ƒ Person(){} 原型对象中指向构造上函数的指针
        console.log(person1)//Person {} //构造函数创建的实例
        console.log(person1.__proto__)//实例内部指针, 指向构造函数的原型对象
        
        // isPortotypeof() 方法来检测实例 和 原型对象之间的关系
        console.log(Person.prototype.isPrototypeOf(person1));//true
        
        //getPrototypeOf() 方法来获取实例内部指针 指向的 原型对象的值
        console.log(Object.getPrototypeOf(person1).name);//Nicholas
        
        //每当有代码要读取某个对象的值时, 都会执行一次搜索,先从该对象的实例中查找, 如果找到则返回该属性的值,如果没找到继续像实例指向的原型对象中寻找,找到则返回该属性的值
        //虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例修改原型对象中的值,在实例中重新给一个属性赋值的话, 那么相对于在实例中创建了该属性, 该属性会屏蔽原型对象中的值
        function Person (){};
        Person.prototype.name = 'jerry';
        Person.prototype.age = 20;
        Person.prototype.job = 'hunter';
        
        var person1 = new Person();
        var person2 = new Person();
        person1.name = 'jack';//修改person1实例中name的值
        console.log(person1.name);//jack 实例中的name属性屏蔽了构造函数的原型对象中的name属性
        console.log(person2.name);//jerry 实例2 的name值还是获取原型对象中的值
        
        //delete 操作符 可以删除实例中的属性
        delete person1.name;//删除了person1实例中的name属性
        console.log(person1.name);//在person1中查询不到name值, 所以继续通过__proto__ 实例内部指针去构造函数原型对象中查找, 结果为jerry
        
        //hasOwnProperty 检测给定属性是否是存在在实例中,是属于实例的属性返回true , 否则返回false
        function Person(){};
        Person.prototype.name = 'Petter';
        Person.prototype.age = 12;
        
        var person1 = new Person();
        var person2 = new Person();
        
        console.log(person.hasOwnProperty('name'));//false
        person1.age = 30;
        console.log(person1.hasOwnProperty('age'));//true
        
        
        
        //in 操作符 : 判断能否通过对象访问到给定属性, 无论属性存在在实例中还是原型对象中, 都返回true
        function Person(){};
        Person.prototype.name = "Betty";
        Person.prototype.age = 16;
        Person.prototype.sayName = function(){
            alert(this.name);
        }
        
        var person1 = new Person();
        var person2 = new Person();
        
        // alert('name' in person1);//true
        console.log(person1.constructor instanceof Person)
        
        person1.name = 'Tom';
        // alert('name' in person1);//true
        // alert('father' in person1);//false 因为father属性即不存在于实例中, 也不存在于原型对象中
        // alert(person1.hasOwnProperty('name'));//true name存在与person1实例中
        
        //for-in 列举对象中可枚举的属性 , [[Enumerable]]特性为false 的属性不会被枚举出来
        var objNameArr = [];
        for(var item in person1){
            console.log(item);
            objNameArr.push(item);
        }
        console.log(objNameArr);// ["name", "age", "job", "sayName"]
        
        var objNameArr = [];
        for(var item in Person.prototype){
            console.log(item);
            objNameArr.push(item);
        }
        console.log(Person.prototype);//构造函数原型对象包含 name age job sayName 和 constructor
        console.log(objNameArr);// ["name", "age", "job", "sayName"] constructor的[[Enumerable]]特性为false ,所以不可枚举
        
        //要获取对象中可枚举的属性可以用Object.keys()方法
        var keys = Object.keys(Person.prototype);
        console.log(keys);// ["name", "age", "job", "sayName"]
        
        //如果要获取对象中的所有属性,无论可枚举和无可枚举 , 可以用方法Object.getOwnPropertyNames()方法
        var keys = Object.getOwnPropertyNames(Person.prototype);
        console.log(keys);//["constructor", "name", "age", "job", "sayName"] constructor 也会存在于数组当中
        
        //更简单的原型模式写法
        var Person = function(){};
        Person.prototype = {
            name :'jerry',
            age:20,
            job:'hunter',
            sayName:function(){
                alert(this.name);
            }
        }
        var person1 = new Person();
        console.log(Person.prototype.constructor);//ƒ Object() { [native code] } 构造函数的原型对象的constructor属性, 不在指向构造函数Person
        console.log(Person.prototype.contructor instanceof Person);//false 原型对象指针constructor不再指向构造函数Person; 如果constructor很重要,可以通过设置
        console.log(person1 instanceof Person) //true
        console.log(person1.constructor == Object);
        console.log(person1.constructor == Person);
        
        //设置constructor
        var Person = function(){};
        Person.prototype = {
            constructor:Person,
            name :'jerry',
            age:20,
            job:"hunter",
            sayName:function(){
                alert(this.name);
            }
        }
        console.log(Person.prototype.constructor == Person);//true 通过这种方式设置的constructor属性是可枚举的, [[Enumerable]]会被设置为true,默认情况下constructor属性是不可枚举的,可以使用Object.defineProperty()方法
        
        
        //原型的动态性
        function Friend(){};
        var girl = new Friend();
        Friend.prototype.sayHi = function(){//sayHi 方法是在创建实例后加的, 下方在实例中调用sayHi方法还是可以成功
            alert('hi');
        }
        // girl.sayHi();//hi 
        
        function Person(){};
        var friend = new Person();
        Person.prototype = {
            name:'jerry',
            age:20,
            job:'hunter',
            sayHi:function(){
                alert(this.name);
            }
        }
        console.log(friend.sayHi);//undefined
        console.log(Person.prototype);
        
        //原生对象的原型
        console.log(Array.prototype);
        
        //为原生对象添加新方法
        String.prototype.startWith = function(text){//不推荐
            return this.indexOf(text)==0;
        }
        var str = 'Hello World';
        console.log(str.startWith('Hello'));//true
        
        
        //组合使用构造函数模式和原型模式  使用度最高的模式
        // 组合模式:就是组合使用构造函数模式和原型模式; 构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性
        function Friend(name,age,job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.firends = ["Shelby", "Court"];
        }
        Friend.prototype = {
            constructor:Friend,
            sayName:function(){
                alert(this.name);
            }
        }
        var firend1 = new Friend("Nicholas", 29, "Software Engineer");
        var firend2 = new Friend("Greg", 27, "Doctor");
        console.log(firend1.firends);
        firend1.firends.push('cao');
        console.log(firend1.firends);//["Shelby", "Court", "cao"] 自己的实例属性
        console.log(firend2.firends);//["Shelby", "Court"]
        // 虽然构造函数和对象字面量都可以用来创建对象,但这些方式都有一个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码.为解决这个问题,人们开始使用工厂模式的一种变体。

相关文章

  • 6_2 创建对象

  • javascript面向对象解析(一)

    创建对象的方式 json对象方式创建对象 Object方式 声明构造函数方式,创建对象 -- 这种创建对象的方式用...

  • JS对象

    JS 创建对象 批量创建对象

  • JavaScript基础—对象

    概论 对象基础 创建对象 利用字面量创建对象: 使用对象 利用new Object创建对象 使用对象方式与上面完全...

  • JS 创建对象的四种方式

    通过对象字面量来创建 通过 new Object() 创建对象 通过工厂函数来创建对象 通过构造函数来创建对象 工...

  • JS笔记-006-JS对象-数字-字符串-日期-数组-逻辑

    JS对象 创建 JavaScript 对象 通过 JavaScript,您能够定义并创建自己的对象。 创建新对象有...

  • 创建对象

    1. 原始方法 2. 工厂方法 3. 构造函数 4. 原型函数 5. 混合构造函数\原型函数 6. 动态原型方法

  • 创建对象

    工厂方式 缺点:1.无法确定对象的类型(因为都是Object)。2.创建的多个对象之间没有关联。3.这个对象的属性...

  • 创建对象

    在ES5中 我们想创建一个对象,人。 我们想克隆多个相似的人怎么办?需要一个函数(资源)创造一个 对象模版(对象制...

  • 创建对象

    工厂模式发明一种函数,用函数来封装以特定接口创建对象的细节。 构造函数模式 使用new操作符,会经历四个步骤 原型...

网友评论

      本文标题:6_2 创建对象

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