Javascript教程(七)——构造函数

一、使用工厂方法创建对象

由于我们在开发中,很多时候,创建的对象,都具有共同的属性,比如:

var obj = {
    
    
	name = "孙悟空";
	age = 18;
	gender = "男";
	sayName = function(){
    
    
		alert(this.name);
	}
};
var obj1 = {
    
    
	name = "猪八戒";
	age = 18;
	gender = "男";
	sayName = function(){
    
    
		alert(this.name);
	}
};

obj与obj2就只有名字是不一样的,如果我们要创建很多这样的对象,这样一个一个创建十分的麻烦,于是就有了下面的使用工厂方法创建对象。

/** 使用工厂方法创建对象
  * 通过该方法可以大批量的创建对象
*/
function createPerson(name, age, gender){
    
    
    //创建一个新的对象 
    var obj = new Object();
    //向对象中添加属性
    obj.name = name;
    obj.age = age;
    obj.gender = gender;
    obj.sayName = function(){
    
    
        alert(this.name);
    };
    //将新的对象返回
    return obj;
}
// 创建三个不同的对象
var obj2 = createPerson("猪八戒",28,"男");
var obj3 = createPerson("白骨精",16,"女");
var obj4 = createPerson("蜘蛛精",18,"女");

console.log(obj2);  //控制台输出{name="猪八戒", age=28, gender="男"}
obj2.sayName();    //alert弹窗输出猪八戒

二 、构造函数

使用工厂方法创建的对象,使用的构造函数都是Object

  • 所以创建的对象都是Object这个类型,就导致我们无法区分出多种不同类型的对象

比如我们再创建一个狗的类型:

function createDog(name , age){
    
    
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sayHello = function(){
    
    
        alert("汪汪~~");
    };
    return obj;
}
//创建一个狗的对象
var dog = createDog("旺财",3);

console.log(dog);
console.log(obj4);  //发现这两个都是object类型,无法区分

在这里插入图片描述

此时就引入了构造函数

  • 创建一个构造函数,专门用来创建Person对象的

    • 构造函数就是一个普通的函数,创建方式和普通函数没有区别, 不同的是 构造函数习惯上首字母大写
    • 构造函数和普通函数的区别就是调用方式的不同
    • 普通函数是直接调用,而构造函数需要使用new关键字来调用
  • 构造函数的执行流程

    1. 立刻创建一个新的对象
    2. 新建的对象,设置为函数中this,在构造函数中可以使用this来引用新建的对象
    3. 逐行执行函数中的代码
    4. 将新建的对象作为返回值返回
  • (※)this的指向情况更新(上一节课只讲了前两种):

  1. 当以函数的形式调用时,this是window
  2. 当以方法的形式调用时,谁调用方法this就是谁
  3. 当以构造函数的形式调用时,this就是新创建的那个对象
    在这里插入图片描述
function Person(name , age , gender){
    
    
	alert(this);   //这里的this 就是用Person构造函数新建的对象per
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = function(){
    
    
    	alert(this.name);
    };
}
var per = new Person("孙悟空",18,"男");
var per2 = new Person("玉兔精",16,"女");
var per3 = new Person("奔波霸",38,"男");

看到这里会觉得,构造函数和工厂方法创建对象很相似,但真的一样吗?

console.log(per);
console.log(per2);
console.log(per3);

输出结果如下:
在这里插入图片描述
我们再创建一个简单的Dog的构造函数,并进行实例化。

function Dog(){
    
    
				
}
var dog = new Dog();
console.log(dog);

在这里插入图片描述
所以我们可以知道:

  • 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类
  • 我们将通过一个构造函数创建的对象称为是该类的实例

JS关键字——instanceof用法

Person和Dog是两个不同的类,那么它们是否有本质上的不同呢?

  • 使用instanceof可以检查一个对象是否是一个类的实例
  • 语法:
    • 对象 instanceof 构造函数
  • 如果是,则返回true,否则返回false
console.log(per instanceof Person);   //true
console.log(dog instanceof Person);   //false

所有的对象都是Object的后代所以任何对象和Object左instanceof检查时都会返回true

console.log(per instanceof Object);   //true
console.log(dog instanceof Object);   //true

三 、构造函数改进

在之前的Person构造函数中,

//创建一个Person构造函数
function Person(name , age , gender){
    
    
	alert(this);   //这里的this 就是用Person构造函数新建的对象per
    this.name = name;
    this.age = age;
    this.gender = gender;
    // 构造函数内部创建sayName方法
    this.sayName = function(){
    
    
    	alert(this.name);
    };
}
  • 在Person构造函数中,为每一个对象都添加了一个sayName方法,目前我们的方法是在构造函数内部创建的
  • 也就是构造函数每执行一次就会创建一个新的sayName方法,也就是所有实例的sayName都是唯一的
  • 如果所有方法都这样写在构造函数内部,就会导致了构造函数执行一次就会创建一个新的方法,执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的。这是完全没有必要,完全可以使所有的对象共享同一个方法。
改进后:将sayName方法在全局作用域中定义
function Person(name , age , gender){
    
    
	this.name = name;
	this.age = age;
	this.gender = gender;
	//向对象中添加一个方法
	this.sayName = fun;
}

//将sayName方法在全局作用域中定义
function fun(){
    
    
	alert("Hello大家好,我是:"+this.name);
};

//创建一个Person的实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");
per.sayName();
per2.sayName();   //per和per2其实调的是同一个函数
console.log(per.sayName == per2.sayName);   // true

但是将函数定义在全局作用域,污染了全局作用域的命名空间(比如有另一个函数不小心也叫了fun这个名字)
而且定义在全局作用域中也很不安全(比如共同开发时,都在全局作用域里定义函数和变量,很容易重复,覆盖)
所以尽量不要在全局作用域中写东西。
于是引入了原型

猜你喜欢

转载自blog.csdn.net/qq_32755875/article/details/110825558