H5W3
当前位置:H5W3 > JavaScript > 正文

【JS】构造函数模式

function createPerson(name,age,job){
let o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){
console.log(this.name);
}
return o;
}
let person1=createPerson('张三',23,'Web前端开发');
let person2=createPerson('李四',20,'IOS开发');

2.还是上面的例子,使用构造函数:

 function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
let person1=new Person('张三',23,'Web前端开发');
let person2=new Person('李四',20,'IOS开发');

3.在这个例子中,Person()构造函数代替了 createPerson()工厂函数。实际上,Person()内部的代码跟 createPerson()基本是一样的,只是有如下区别。

1.没有显式地创建对象。
2.属性和方法直接赋值给了 this 。
3.没有 return 。

4.要创建 Person 的实例,应使用 new 操作符。以这种方式调用构造函数会执行如下操作。

5.上一个例子的最后,person1和person2分别保存着 Person 的不同实例。这两个对象都有一个 constrctor 属性指向 Person,如下所示:

console.log(person1.constructor===Person); // true
console.log(person2.constructor===Person); //true

6.constructor本来是用于标识对象类型的。不过,一般认为 instanceof 操作符是确定对象类型更可靠的方式。前面例子中每个对象都是 Object的实例,同时也是 Person 的实例,如下面调用 instanceof 操作符的结果所示:

console.log(person1 instanceof Person); // true
console.log(person1 instanceof Object); // true
console.log(person2 instanceof Person);
console.log(person2 instanceof Object);  // true

7.构造函数不一定携程函数声明的形式。赋值给变量的函数表达式也可以表示构造函数:

let Person=function(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
};
}
let person1=new Person('张三',23,'Web前端开发');
let person2=new Person('李四',20,'IOS开发');
person1.sayName(); // 张三
person2.sayName(); // 李四
console.log(person1 instanceof Object);// true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person);// true

8.在实例化时,如果不想传参数,那么构造函数后面的括号可加可不加。只要有new操作符,就可以调用相应的构造函数:

function Person(){
this.name='陈';
this.sayName=function(){
console.log(this.name);
}
}
let person1=new Person();
let person2=new Person();
person1.sayName();// 陈
person2.sayName();// 陈
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person);//true

9.构造函数也是函数。构造函数与普通函数唯一区别就是调用方式不同。除此之外,构造函数也是函数。并没有把某个函数定义为构造函数的特殊语法。任何函数只要使用 new 操作符就是构造函数,而不使用 new操作符调用的函数就是普通函数。比如,前面的例子中定义的 Person()可以像下面这样调用:

//作为构造函数
let person=new Person('张三',23,'Web前端开发');
person.sayName();// 张三
//作为函数调用
Person('陈',23,'Web前端开发');
window.sayName(); // '陈'
//在另外一个对象的作用域中调用
let o=new Object();
Person.call(o,'李四',20,'IOS开发');
o.sayName(); // '李四'

10.构造函数的问题。构造函数虽然有用,但也不是没有问题。构造函数的主要问题在于,其定义的方法会在每个实例上都会创建一遍。因此对前面的例子而言,person1和person2都有名为 sayName()的方法,但这个方法不是同一个 Function实例。我们知道,ECMAScript中的函数是对象,因此每次定义函数时,都会初始化一个对象。逻辑上讲,这个构造函数实际上时这样的:

function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=new Function("console.log(this.name)");  //逻辑等价
}

11.这样理解这个狗构造函数可以更清楚地知道,每个 Person实例都会有自己的 Function 实例用于显示 name 属性。当然了,以这种方式创建函数会带来不同的作用域链和表示解析。但创建新 Function 实例的机制时一样的。因此不同实例上的函数虽然同名却不相等,如下所示:

console.log(person1.sayName===person2.sayName);//false

12.因为都是在做一样的事,所以没必要定义两个不同的 Function 实例。况且,this对象可以把函数与对象的绑定推迟到运行时。要解决这个问题,可以把函数定义转移到构造函数外部:

function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=sayName;
}
function sayName(){
console.log(this.name);
}
let person1=new Person("张三",23,"Web前端开发");
let person2=new Person("李四",20,"IOS开发");

13.本期的分享到了这里就结束啦,希望对你有所帮助,让我们一起努力走向巅峰!

本文地址:H5W3 » 【JS】构造函数模式

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址