构造函数

在ES6中,JavaScript引入了类的概念,可以基于类创建一个对象,但在ES6之前,对象不是基于类创建的,而是通过构造函数和其他方法来创建的。

构造函数是一种特殊的函数。构造函数可以定义属性的特征和方法。构造函数可以理解为对象的模板。

构造函数创建对象

在ES6之前,创建对象的方法有三种:

1. 对象字面量

var objname={

属性名:属性值

};

2. new Object()

var objname=new Object()

objname.属性名=属性值
3. 自定义构造函数

注意:构造函数的首字母要大写

function Person(uname, age) {
        this.uname = uname;
        this.age = age;
    }

 

 然后通过new关键字创建一个Person的实例对象

var student= new Person('张三', 18);

 

new关键字创建实例对象的过程

1.在内存中创建一个新对象。

2.将构造函数中的this指向这个新对象。

3.将构造函数的prototype属性赋值给新对象内部的[[prototype]]

4.执行构造函数内部的代码,给新对象添加属性。

5.如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

构造函数成员

构造函数成员分为静态成员和实例成员

实例成员

在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问

function Person(uname, age) {
        this.uname = uname;    //实例成员
        this.age = age;
    }

 

静态成员

在构造函数本上添加的成员称为静态成员,只能由构造函数本身来访问

function Person(uname, age) {
        this.uname = uname;
        this.age = age;
        this.sing = function () {    //实例成员
            console.log("我会唱、跳、rap");
        }

    }
Person.sex = "男";    //静态成员

 

构造函数问题

当new一个构造函数对象时,构造函数就会执行一遍,开辟一个新的内存空间,每次都创建一些新的属性和方法function,每次都指向一个新的对象,这样占用内存消耗非常大。而构造函数原型对象Prototype可以解决这样的方法。因为对象的方法或属性可以从构造函数的原型对象prototype上获取。

。function Person(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌'); }
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);

 

function 定义构造函数 构造函数定义对象_function 定义构造函数

 

 

构造函数(原型对象Prototype)

JavaScript 规定,所有的函数,包括构造函数都有一个 prototype 属性,指向另一个对象(原型链上面的),注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。我们把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

function Person(uname, age) {
        this.uname = uname;
        this.age = age;
    }
    Person.prototype.sing = function () {
        console.log("我会唱、跳、rap");
    }

    var person1= new Person('张三', 18);
    var person2= new Person('李四', 20);
    console.log(person1.sing === person2.sing);
    person1.sing();
    person2.sing();

 

对象原型 __proto__

JS 在创建对象的时候,都有一个__proto__ 的内置属性,用于指向创建它的构造函数的原型对象。

function Fruit(name, price) {
        this.name = name
        this.price = price
    }
var apple = new Fruit('apple', 10)

 console.log(apple.__proto__ === Fruit.prototype);

//excepted output:true

 

constructor 构造函数

对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

实例对象使用constructor属性指回构造函数。

原型对象prototype使用constructor只会构造函数。

constructor的应用场景

一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

示例:

function Star(uname, age) {
        this.uname = uname;
        this.age = age;
    }
    /*  Star.prototype.sing = function () {
         console.log("我会唱、跳、rap");
     }
     Star.prototype.movie = function () {
         console.log("我会跳舞");
     } */
    Star.prototype = {
        // 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
        constructor: Star,
        sing: function () {
            console.log("我会唱、跳、rap");
        },
        movie: function () {
            console.log("我会跳舞");
        }
    }

 

 

 

function 定义构造函数 构造函数定义对象_原型对象_02

 

 

 

 

 

 

 

 

 

 

 

 

 

继承与原型链

继承

JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

原型链

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

function 定义构造函数 构造函数定义对象_原型链_03

 

 

JavaScript成员 查找机制

①当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
②如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
③如果还没有就查找原型对象的原型(Object的原型对象)。
④依此类推一直找到 Object 为止(null)。
⑤__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。

 

由于原型链的存在,因此我们可以调用一些不存在与该对象属性的方法,因为这些方法存在于原型链的Object的原型对象上。