专业游戏门户,分享手游网游单机游戏百科知识攻略!

嗨游网
嗨游网

什么是构造函数?详解JavaScript中的构造函数

来源:小嗨整编  作者:小嗨  发布时间:2024-03-21 07:50
摘要:作为原型和原型链的基础,先了解清楚构造函数以及它的执行过程才能更好地帮助我们学习原型和原型链的知识。本篇文章带大家详细了解一下javascript中的构造函数,介绍一下怎么利用构造函数创建一个js对象,希望对大家有所帮助!一个普通的函数被用...

作为原型和原型链的基础,先了解清楚构造函数以及它的执行过程才能更好地帮助我们学习原型和原型链的知识。本篇文章带大家详细了解一下javascript中的构造函数,介绍一下怎么利用构造函数创建一个js对象,希望对大家有所帮助!

什么是构造函数?详解JavaScript中的构造函数

一个普通的函数被用于创建一个类对象时,它就被称作构造函数,或者构造器。(为方便理解,你可以将JavaScript中构造器的创建理解为其他语言中的类的创建,目的就是利用它通过new来实列一个对象)

function Person(){//...}//当做普通函数调用var obj=Person();//构造函数调用 var obj=new Person();
登录后复制

构造函数的特点:

在书写规范上,我们习惯将构造函数名称的首字母大写。

通过new来创建一个对象。

无需在内写入return也会有返回值,而且返回的是一个对象。

利用构造函数创建一个js对象

构造函数创建对象(方法写在构造函数里,缺点:构造函数每执行一次, 就会创建一次方法。)

  function Person(name,age,gender){            this.name=name;            this.age=age;            this.gender=gender;            // 方法写在里面            this.sayName=function(){                 console.log(this.name);             }                }              function Dog(name,age){              this.name=name;              this.age=age;          }                   var obj=new Person("张三",18,"男");          var obj1=new Person("李四",16,"男");                    var dog=new Dog("乐乐",2);          obj.sayName();          obj1.sayName();                    console.log(obj);          console.log(obj1);          console.log(dog);
登录后复制

构造函数创建对象(方法写在构造函数外,缺点: 方法为全局方法,污染全局。)

   function Person(name,age,gender){            this.name=name;            this.age=age;            this.gender=gender;            this.sayName=fun;   //方法写在外面          }     function fun(){            console.log(this.name);        }          function Dog(name,age){              this.name=name;              this.age=age;          }                    var obj=new Person("张三",18,"男");          var obj1=new Person("李四",16,"男");                    var dog=new Dog("乐乐",2);          obj.sayName();          obj1.sayName();                    console.log(obj);          console.log(obj1);          console.log(dog);
登录后复制

构造函数创建对象改造(方法通过原型对象创建)

原型对象:prototype

我们所创建的每一个函数,解析器都会向函数中添加一个prototype属性。

指向构造函数的原型对象,我们可以通过__proto__来访问该属性。

构造函数.prototype.xxx , xxx可以是变量,可以是方法。执行过程中会先去对象中找方法或者变量, 找不到就会去原型里寻找。

  function Person(name,age,gender){            this.name=name;            this.age=age;            this.gender=gender;          }          function Dog(name,age){              this.name=name;              this.age=age;          }                  /*为person添加统一的方法, 到原型对象中*/        Person.prototype.sayName=function(){            console.log(this.name);        }          var obj=new Person("张三",18,"男");          var obj1=new Person("李四",16,"男");                    var dog=new Dog("乐乐",2);          obj.sayName();          obj1.sayName();                    console.log(obj);          console.log(obj1);          console.log(dog);
登录后复制

运行结果:

学习每一个概念,不仅要知道它是什么,还要知道为什么,以及解决什么样的问题。

举个例子,我们要录入一年级一班中每一位同学的个人信息,那么我们可以创建一些对象,比如:

var p1 = { name: 'zs', age: 6, gender: '男', hobby: 'basketball' };var p2 = { name: 'ls', age: 6, gender: '女', hobby: 'dancing' };var p3 = { name: 'ww', age: 6, gender: '女', hobby: 'singing' };var p4 = { name: 'zl', age: 6, gender: '男', hobby: 'football' };// ...
登录后复制

像上面这样,我们可以把每一位同学的信息当做一个对象来处理。但是,我们会发现,我们重复地写了很多无意义的代码。比如 name、age、gender、hobby 。如果这个班上有60个学生,我们得重复写60遍。

这个时候,构造函数的优势就体现出来了。我们发现,虽然每位同学都有 name、gender、hobby这些属性, 但它们都是不同的,那我们就把这些属性当做构造函数的参数传递进去。而由于都是一年级的学生,age 基本都是6岁,所以我们就可以写死,遇到特殊情况再单独做处理即可。此时,我们就可以创建以下的函数:

function Person(name, gender, hobby) {    this.name = name;    this.gender = gender;    this.hobby = hobby;    this.age = 6;}
登录后复制

当创建上面的函数以后, 我们就可以通过 new 关键字调用,也就是通过构造函数来创建对象了。

var p1 = new Person('zs', '男', 'basketball');var p2 = new Person('ls', '女', 'dancing');var p3 = new Person('ww', '女', 'singing');var p4 = new Person('zl', '男', 'football');// ...
登录后复制

此时你会发现,创建对象会变得非常方便。所以,虽然封装构造函数的过程会比较麻烦,但一旦封装成功,我们再创建对象就会变得非常轻松,这也是我们为什么要使用构造函数的原因。

在使用对象字面量创建一系列同一类型的对象时,这些对象可能具有一些相似的特征(属性)和行为(方法),此时会产生很多重复的代码,而使用构造函数就可以实现代码复用

先说一点基本概念。

function Animal(color) { this.color = color;}
登录后复制

当一个函数创建好以后,我们并不知道它是不是构造函数,即使像上面的例子一样,函数名为大写,我们也不能确定。只有当一个函数以 new 关键字来调用的时候,我们才能说它是一个构造函数。就像下面这样:

var dog = new Animal("black");
登录后复制

以下我们只讨论构造函数的执行过程,也就是以 new 关键字来调用的情况。

我们还是以上面的 Person 为例。

function Person(name, gender, hobby) { this.name = name; this.gender = gender; this.hobby = hobby; this.age = 6;}var p1 = new Person('zs', '男', 'basketball');
登录后复制

此时,构造函数会有以下几个执行过程:

1)当以 new 关键字调用时,会创建一个新的内存空间,标记为 Animal 的实例。

2)函数体内部的 this 指向该内存

通过以上两步,我们就可以得出这样的结论。

var p2 = new Person('ls', '女', 'dancing');  // 创建一个新的内存 #f2var p3 = new Person('ww', '女', 'singing');  // 创建一个新的内存 #f3
登录后复制

每当创建一个实例的时候,就会创建一个新的内存空间(#f2, #f3),创建 #f2 的时候,函数体内部的 this 指向 #f2, 创建 #f3 的时候,函数体内部的 this 指向 #f3。

3) 执行函数体内的代码 通过上面的讲解,你就可以知道,给 this 添加属性,就相当于给实例添加属性。

4)默认返回 this

由于函数体内部的this指向新创建的内存空间,默认返回 this ,就相当于默认返回了该内存空间,也就是上图中的 #f1。此时,#f1的内存空间被变量p1所接受。也就是说 p1 这个变量,保存的内存地址就是 #f1,同时被标记为 Person 的实例。

以上就是构造函数的整个执行过程。

构造函数执行过程的最后一步是默认返回 this 。言外之意,构造函数的返回值还有其它情况。下面我们就来聊聊关于构造函数返回值的问题。

1)没有手动添加返回值,默认返回 this

function Person1() { this.name = 'zhangsan';}var p1 = new Person1();
登录后复制

按照上面讲的,我们复习一遍。首先,当用 new 关键字调用时,产生一个新的内存空间 #f11,并标记为 Person1 的实例;接着,函数体内部的 this 指向该内存空间 #f11;执行函数体内部的代码;由于函数体内部的this 指向该内存空间,而该内存空间又被变量 p1 所接收,所以 p1 中就会有一个 name 属性,属性值为 ‘zhangsan’。

p1: { name: 'zhangsan'}
登录后复制

2)手动添加一个基本数据类型的返回值,最终还是返回 this

function Person2() { this.age = 28; return 50;}var p2 = new Person2();console.log(p2.age);   // 28p2: { age: 28}
登录后复制

如果上面是一个普通函数的调用,那么返回值就是 50。

3)手动添加一个复杂数据类型(对象)的返回值,最终返回该对象

直接上例子

function Person3() { this.height = '180'; return ['a', 'b', 'c'];}var p3 = new Person3();console.log(p3.height);  // undefinedconsole.log(p3.length);  // 3console.log(p3[0]);      // 'a'
登录后复制

再来一个例子

function Person4() {  this.gender = '男';  return { gender: '中性' };}var p4 = new Person4();console.log(p4.gender);  // '中性'
登录后复制

大小写都可以

如果不会出错,那么,用new和不用new调用构造函数,有什么区别?

1)使用new操作符调用函数

例子:

function Person(name){  this.name = name;  this.say = function(){    return "I am " + this.name;  }}var person1 = new Person('nicole');person1.say(); // "I am nicole"
登录后复制

用new调用构造函数,函数内部会发生如下变化:

创建一个this变量,该变量指向一个空对象。并且该对象继承函数的原型; 属性和方法被加入到this引用的对象中; 隐式返回this对象(如果没有显性返回其他对象) 用伪程序来展示上述变化:

function Person(name){  // 创建this变量,指向空对象  var this = {};   // 属性和方法被加入到this引用的对象中  this.name = name;  this.say = function(){    return "I am " + this.name;  }  // 返回this对象  return this;}
登录后复制

可以看出,用new调用构造函数,最大特点为,this对象指向构造函数生成的对象,所以,person1.say()会返回字符串: “I am nicole”。

小贴士:如果指定了返回对象,那么,this对象可能被丢失。

function Person(name){  this.name = name;  this.say = function(){    return "I am " + this.name;  }  var that = {};  that.name = "It is that!";  return that;}var person1 = new Person('nicole');person1.name; // "It is that!"
登录后复制

2)直接调用函数

如果直接调用函数,那么,this对象指向window,并且,不会默认返回任何对象(除非显性声明返回值)。

还是拿Person函数为例,直接调用Person函数:

var person1 = Person('nicole');person1; // undefinedwindow.name; // nicole
登录后复制

可见,直接调用构造函数的结果,并不是我们想要的。

3)小结

为了防止因为忘记使用new关键字而调用构造函数,可以加一些判断条件强行调用new关键字,代码如下:

function Person(name){  if (!(this instanceof Person)) {    return new Person(name);  }  this.name = name;  this.say = function(){    return "I am " + this.name;  }}var person1 = Person('nicole');console.log(person1.say()); // I am nicolevar person2 = new Person('lisa');console.log(person2.say()); // I am lisa
登录后复制

【相关推荐:javascript学习教程

以上就是什么是构造函数?详解JavaScript中的构造函数的详细内容,更多请关注易企推科技其它相关文章!


本文地址:网络百科频道 https://www.eeeoo.cn/wangluo/1151930.html,嗨游网一个专业手游免费下载攻略知识分享平台,本站部分内容来自网络分享,不对内容负责,如有涉及到您的权益,请联系我们删除,谢谢!


网络百科
小编:小嗨整编
相关文章相关阅读
  • 阴阳师辉夜姬带什么御魂(阴阳师辉夜姬值得养吗)?

    阴阳师辉夜姬带什么御魂(阴阳师辉夜姬值得养吗)?

    阴阳师辉夜姬带什么御魂(阴阳师辉夜姬值得养吗)?辉夜姬作为阴阳师中的一位强力辅助式神,凭借其独特的技能和强大的辅助能力,成为了许多玩家心仪的选择。那么辉夜姬究竟带什么御魂才能发挥最大潜力呢?本文将为您详细介绍辉夜姬的御魂搭配,并分析其值得养...

  • 阴阳师青行灯什么时候出的(阴阳师青行灯值得培养吗)?

    阴阳师青行灯什么时候出的(阴阳师青行灯值得培养吗)?

    阴阳师青行灯什么时候出的(阴阳师青行灯值得培养吗)?随着阴阳师这款手游的火热,各种式神层出不穷,其中SSR级别的式神更是备受玩家关注。青行灯作为SSR中的常青树,自出道以来便以其独特的技能和强大的实力,吸引了无数玩家的目光。阴阳师青行灯什么...

  • 阴阳师彼岸花什么时候出的(阴阳师彼岸花值得练吗)?

    阴阳师彼岸花什么时候出的(阴阳师彼岸花值得练吗)?

    阴阳师彼岸花什么时候出的(阴阳师彼岸花值得练吗)?彼岸花作为阴阳师中的SSR式神,首次出现在游戏中是在2016年。随后,官方推出了SP版本的彼岸花,名为“夜溟彼岸花”,并于2021年1月6日正式上线。阴阳师彼岸花值得练吗彼岸花的技能设计非常...

  • 魔兽世界泰兰德是什么职业(魔兽世界泰兰德幻化怎么获得)?

    魔兽世界泰兰德是什么职业(魔兽世界泰兰德幻化怎么获得)?

    魔兽世界泰兰德是什么职业(魔兽世界泰兰德幻化怎么获得)?在魔兽世界中,泰兰德是魔兽世界中暗夜精灵种族的代表性角色,她以牧师职业为主。牧师在游戏中拥有强大的治疗和辅助能力,是团队中不可或缺的重要角色。泰兰德作为一名牧师,擅长使用圣光和暗影之力...

  • lol小丑的名字叫什么(lol小丑怎么分辨真假)?

    lol小丑的名字叫什么(lol小丑怎么分辨真假)?

    lol小丑的名字叫什么(lol小丑怎么分辨真假)?在lol英雄联盟中,小丑(Janna)作为一位辅助英雄,以其独特的技能和出色的辅助能力深受玩家喜爱。然而,许多玩家在游戏中可能遇到真假小丑难以辨别的问题。本文将为大家详细解析LOL小丑的名字...

  • lol老鼠叫什么(lol老鼠技能介绍)?

    lol老鼠叫什么(lol老鼠技能介绍)?

    lol老鼠叫什么(lol老鼠技能介绍)?在lol中,老鼠这位英雄正式名称为“瘟疫之源·图奇”。他以其独特的毒液技能和隐身能力,在游戏中扮演着一名出色的刺客和骚扰者。以下是关于老鼠的详细技能介绍:lol老鼠技能介绍一、被动技能——死亡毒液老鼠...

  • dnf红玉髓是干什么用的(dnf红玉髓在哪里兑换)?

    dnf红玉髓是干什么用的(dnf红玉髓在哪里兑换)?

    dnf红玉髓是干什么用的(dnf红玉髓在哪里兑换)?在dnf中,红玉髓是一种非常有用的材料,它不仅能够兑换圣物装备,还能换取各种药剂,对于玩家来说,掌握红玉髓的用途和兑换地点至关重要。dnf红玉髓是干什么用的1.兑换圣物装备:红玉髓是制作圣...

  • 闲鱼app什么时候上线的(闲鱼app官网)?

    闲鱼app什么时候上线的(闲鱼app官网)?

    闲鱼app什么时候上线的(闲鱼app官网)?闲鱼App,原名为“闲鱼二手交易”,作为阿里巴巴集团旗下的知名二手交易平台,自上线以来,受到了广大用户的喜爱。本文将揭秘闲鱼App的上线时间,带您了解闲鱼官网的起源与发展。闲鱼app上线于2015...

  • 周排行
  • 月排行
  • 年排行

精彩推荐