對,每個類別只能有一個建構函數,如果包含多個建構函數,那麼就會拋出異常。建構函數是一種特殊的函數,主要用來初始化對象,即為對象成員變數賦初始值;使用建構子時要注意兩點:1、建構子用來建立某一類對象,其首字母要大寫;2、建構函數要和new一起使用才有意義。
本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
在典型的OOP 的語言中(如Java),都存在類別的概念,類別就是物件的模板,物件就是類別的實例,但在ES6之前, JS 中並沒用引入類別的概念。
在 ES6之前 ,物件不是基於類別創建的,而是用一種稱為建構函數的特殊函數來定義物件和它們的特徵。
建立物件可以透過以下三種方式:
物件字面量
new Object()
自訂建構子
// 1、利用 new Object() 创建对象 var obj1 = new Object(); // 2、利用对象字面量创建对象 var obj2 = {}; // 利用构造函数创建对象 function Star(name,age) { this.name=name; this.age=age; this.sing=function(){ console.log('唱歌'); } } var ldh=new Star('刘德华',23); console.log(ldh); ldh.sing(); // Star { name: '刘德华', age: 23, sing: [Function (anonymous)] } //唱歌
#建構子
##建構子是一種特殊的函數,主要用來初始化對象,即為對象成員變數賦初始值,它總是與new 一起使用。我們可以把物件中一些公共的屬性和方法抽取出來,然後封裝到這個函數裡面。 在JS 中,使用建構子時要注意以下兩點:// 类的声明 class Person { // 类的构造方法 注:一个类只能有一个构造函数, 如果没有定义那就自动用默认的 // 通过new关键字操作类的时候,会调用constructor函数,并执行如下操作 // 1、在内存中创建一个对象 moni = {} // 2、 将类的原型prototype赋值给创建出来的对象 moni.__proto__ = Person.prototype // 3、将对象赋值给函数的this:new绑定 this = moni // 4、执行函数中的代码 // 5、自动返回创建出来的对象 constructor() { } } let p1 = new Person() let P2 = new Person('kobe', 30)
new 在執行時會做四件事:
(1)在記憶體中建立一個新的空對象。 (2)讓 this 指向這個新的物件。 (3)執行建構子裡面的程式碼,為這個新物件新增屬性和方法。 (4)回傳這個新物件(所以建構函式裡面不需要 return )。 JavaScript 的建構函式中可以加入一些成員,可以在建構函式本身上加,也可以在建構函式內部的 this 上加入。透過這兩種方式加入的成員,就分別稱為靜態成員和實例成員。// 构造函数中的属性和方法称为成员 function Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌'); } } var ldh = new Star('刘德华', 18); // 1、实例成员就是构造函数内部通过this添加的成员 // uname、age、sing就是实例成员 // 实例成员只能通过实例化的对象来访问 console.log(ldh.uname); //刘德华 ldh.sing(); //我会唱歌 // 不可以通过构造函数来访问实例成员 console.log(Star.uname); //undefined Star.sex='男' // 2、静态成员 在构造函数本身上添加的成员 sex 就是静态成员 // 静态成员只能通过构造函数来访问 console.log(Star.sex); //男 // 静态成员不能通过对象来访问 console.log(ldh.sex); //undefined
建構函數的問題
建構子方法很好用,但是有浪費記憶體的問題。 我們希望所有的物件都使用同一個函數,這樣就比較節省內存,那麼我們要怎麼做呢?建構子原型 prototype
建構子透過原型分配的函數是所有物件所共享的。 JavaScript 規定,每個建構函式都有一個 prototype 屬性,指向另一個物件。注意這個 prototype 就是一個對象,這個物件的所有屬性和方法,都會被建構函式所擁有。 我們可以把那些不變的方法,直接定義在 prototype 物件上,這樣所有物件的實例就可以共享這些方法。 列印物件的屬性,查看prototypefunction Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌'); } } console.dir(Star);
function Star(uname, age) { this.uname = uname; this.age = age; // this.sing=function() { // console.log('我会唱歌'); // } } Star.prototype.sing=function() { console.log('我会唱歌'); } var ldh= new Star('刘德华',18); var zxy= new Star('张学友',19); console.log(ldh.sing===zxy.sing); //采用this添加方法时输出 false 采用prototype添加方法时输出 true ldh.sing(); zxy.sing();
物件原型__proto__
物件都會有一個屬性__proto__指向建構函數的prototype 原型對象,之所以我們物件可以使用建構子prototype 原型物件的屬性與方法,就是因為物件有__proto__原型的存在。 __proto__物件原型和原型物件prototype 是等價的__proto__物件原型的意義就在於為物件的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型物件prototype#
function Star(uname, age) { this.uname = uname; this.age = age; } Star.prototype.sing=function(){ console.log('我会唱歌'); } var ldh = new Star('刘德华', 18); var zxy = new Star('张学友', 19); console.log(ldh); //对象身上系统自己添加一个__proto__ 指向构造函数的原型对象 prototype console.log(ldh.__proto__===Star.prototype); //true // 方法的查找规则(以sing方法为例): // 首先看 实例对象身上是否有 sing 方法,如果有就执行这个对象的sing // 如果没有sing 方法,因为有__proto__的存在,就去 构造函数原型对象prototype身上找sing 方法
constructor 构造函数
对象原型__proto__和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
function Star(uname, age) { this.uname = uname; this.age = age; } Star.prototype = { // 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数 constructor: Star, sing: function() { console.log('我会唱歌'); }, movie: function() { console.log('我会演电影'); } } var ldh = new Star('刘德华', 18); console.log(Star.prototype.constructor); console.log(ldh.__proto__.constructor);
给原型对象采取对象形式赋值,会覆盖构造函数原型对象原来的内容,就不会有constructor指向当前构造函数
Star.prototype = { sing: function() { console.log('我会唱歌'); }, movie: function() { console.log('我会演电影'); } } console.dir(Star);
解决办法:手动的利用constructor指回原来的构造函数
Star.prototype = { // 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数 constructor: Star, sing: function() { console.log('我会唱歌'); }, movie: function() { console.log('我会演电影'); } }
构造函数、实例、原型对象三者之间的关系
【相关推荐:javascript视频教程、编程视频】
以上是es6建構函式只能有一個嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!