资讯专栏INFORMATION COLUMN

js创建对象方法与过程+ES6的class

GitChat / 703人阅读

摘要:改进方法方法一通过先执行一次的原型重写写在创建对象之前输出方法二提前先执行一次初次运行时,多调用一次输出中的相当于中的构造函数,如果不写默认为空,定义在对象自身上面该方法定义在上输出可以说,用法就是中动态原型模式。

js创建对象有很多方法,以下是常见方法整理。

ES5创建对象 工厂模式
function person (name, age, sex) {
    var O = new Object();
    O.name = name;
    O.age = age;
    O.sex = sex;
    O.sayName =function(){
        console.log(this.name);
    }
    return O;
}
var per = person("per",10,"male"); //不需要用new,因为有return,就是个普通函数,很好理解
console.log(per instanceof person); //false
构造函数模式
function Person (name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayName =function(){
        console.log(this.name);
    }
}
var per =new Person("per",10,"male"); 
console.log(per instanceof Person); //true

分析创建过程,

 var per =new Person("per",10,"male"); 

在这行代码执行时,四个步骤:
①出现了一个空的对象
②this指向这个对象
③执行构造函数的代码
④把这个对象取个名字是per,per的指针就指向这个对象,于是可以通过per操作这个对象

工厂模式定义出的对象,instanceof识别不出是"person类"。
构造函数模式,每次new一个对象,里面的函数都会创建一次,就这个sayName函数,明明共有同一个就可以了。
解决这个问题,出现了原型模式:

原型模式
function Person () {
    Person.prototype.name = "p1";
    Person.prototype.age = 10;
    Person.prototype.sex = "female";
    Person.prototype.sayName =function(){
        console.log(this.name);
    }
}

那么,这些代码干了什么呢?
①当你创建Person()函数后,就会有一个prototype属性随之而来
我们可以看看,这个prototype是什么,执行以下代码:

 console.log(Person.prototype);

_proto_保存继承自Object的方法。里面只有一个constructor属性指向Person()函数自身。
②当然我们是要用这个函数的,执行以下代码:

var per1 =new Person();
var per2 =new Person();
console.log(Person.prototype);

在创建实际对象时候,就会运行构造函数中的代码,而且per1、per2两个对象,就会执行两次构造函数的代码,但并不会多创建一个Person的prototype属性,只是重新赋值里面的name、age、sex和sayName变量。
③per1和per2有各自的prototype属性,指向Person的prototype属性。可以简单理解为per1、per2各自的"指针"指向同一个"对象"。

这个原型模式啊,就真的好像单例模式了,每个创建的对象都在操作同一个对象。

最优:动态原型模式
function Person (name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    if(typeof this.sayName != "function"){  
        Person.prototype.sayName = function(){
            console.log(this.name);
        }
        Person.prototype.sayAge = function(){
            console.log(this.age);
        }
    }
}
var per = new Person("wlq", 19, "man");

这样的代码,使得每个对象的name、age、sex都是各自的(不共有),然后函数写在原型上,就又是共享的,很不错。还有个地方,if语句的判断,使得第二次创建对象时候,不会重新给Person.prototype.sayName和Person.prototype.sayAge重赋值。

原型重写的问题
function Person (name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            console.log(this.name);
        }
    }
}
function WPerson (name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    if(typeof this.sayName != "function"){
        WPerson.prototype = {   //这里进行了原型的重写
            constructor: WPerson,
            sayName: function(){
                console.log(this.name);
            }
        }
    }
}
var per1 = new Person("w", 19, "man");
var per2 = new WPerson("q", 18, "man");
var per3 = new WPerson("q", 18, "man");
per1.sayName();  //输出w
per2.sayName();  //报错,说没有sayName这个方法
per3.sayName();  //输出q
console.log(per2.name);  //输出q
原因

重写原型的发生是在创建对象之后的,per2指向的WPerson的原型上面只有name、age、sex,再创建完per2后,才执行WPerson原型的重写,per3甚至以后创建的WPerson类型对象就都会有sayName函数了。

改进方法

方法一(通过先执行一次WPerson的原型重写):

function WPerson (name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;       
}
WPerson.prototype = {  //写在创建对象之前
    constructor:WPerson,
    sayName: function(){
        console.log(this.name);
    }
}
var per = new WPerson("q", 18, "man");
per.sayName();  //输出q

方法二(提前先执行一次new):

   function WPerson (name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;  
        if(typeof this.sayName != "function"){
            WPerson.prototype = {  
                constructor:WPerson,
                sayName: function(){
                    console.log(this.name);
                }
            };
            return new WPerson(name,age,sex);  //初次运行时,多调用一次new
           }
    }     
    var per = new WPerson("q", 18, "man");
    per.sayName();  //输出q
   

ES6中的class
class Point{
  constructor(x, y) {    //相当于java中的构造函数,如果不写默认为空
    this.x = x;          //x,y定义在对象自身上面
    this.y = y;
  }
  add() {                //该方法定义在Point.prototype上
    console.log(this.x + this.y);
  }
}
var p = new Point(2, 3);
p.add();  //输出5

可以说,class用法就是ES5中动态原型模式。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93259.html

相关文章

  • es6js

    摘要:生成的类的原型会被自动调整,而你还能调用方法来访问基类的构造器。唯一能避免调用的办法,是从类构造器中返回一个对象。 起源 JS 从创建之初就不支持类,也没有把类继承作为定义相似对象以及关联对象的主要方式,这让不少开发者感到困惑。而从 ES1 诞生之前直到ES5 时期,很多库都创建了一些工具,让 JS 显得貌似能支持类。尽管一些 JS 开发者强烈认为这门语言不需要类,但为处理类而创建的代...

    libin19890520 评论0 收藏0
  • JavaScript面向对象核心知识归纳

    摘要:一面向对象概念面向对象就是使用对象。因此在构造函数中表示刚刚创建出来的对象。在构造函数中利用对象的动态特性为其对象添加成员。 一、面向对象 1.1 概念 面向对象就是使用对象。面向对象开发就是使用对象开发。 面向过程就是用过程的方式进行开发。面向对象是对面向过程的封装。 1.2 三大特性 抽象性所谓的抽象性就是:如果需要一个对象描述数据,需要抽取这个对象的核心数据 提出需要的核心...

    TalkingData 评论0 收藏0
  • js对象详解(JavaScript对象深度剖析,深度理解js对象)

    摘要:对象详解对象深度剖析,深度理解对象这算是酝酿很久的一篇文章了。用空构造函数设置类名每个对象都共享相同属性每个对象共享一个方法版本,省内存。 js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了。 JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕。 平时发的文章基本都是开发中遇到的问题和对...

    CatalpaFlat 评论0 收藏0
  • 剖析JS原型链和继承

    摘要:接下来我们来聊一下的原型链继承和类。组合继承为了复用方法,我们使用组合继承的方式,即利用构造函数继承属性,利用原型链继承方法,融合它们的优点,避免缺陷,成为中最常用的继承。 JavaScript是一门面向对象的设计语言,在JS里除了null和undefined,其余一切皆为对象。其中Array/Function/Date/RegExp是Object对象的特殊实例实现,Boolean/N...

    darkerXi 评论0 收藏0
  • JS之理解ES6 继承extends

    摘要:理解继承在中对继承有了更友好的方式。总的来说的的实质和以前的继承方式是一致的,但是有了更好的,更清晰的表现形式。 理解ES6继承extends 1.在es6中对继承有了更友好的方式。在下面的继承中那到底在extends的时候做了什么,super()又是代表什么意思。 class People{ constructor(name, age) { this.name = name; ...

    starsfun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<