900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 详解JavaScript创建对象——构造函数模式

详解JavaScript创建对象——构造函数模式

时间:2024-01-22 07:52:50

相关推荐

详解JavaScript创建对象——构造函数模式

文章目录

一、什么是构造函数?二、构造函数与普通函数的区别 1.new2.new.target三、使用构造函数四、构造函数的问题总结

一、什么是构造函数?

在一些面向对象的语言,如Java、C++、PHP中,构造函数是很常见的。在Javascript中构造函数首先是一个普通的函数,它可以使用new操作符来调用,并生成一个特殊类型的对象

例如:

// 构造函数模式为对象定义属性和方法function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.sayName = function () {console.log(this.name);}}// 使用new操作符为构造函数创建对象let person_1 = new Person("Nicholas", 29, "Software Engineer");person_1.sayName(); // Nicholaslet person_2 = new Person("Greg", 27, "Doctor");person_2.sayName(); // Greg

二、构造函数与普通函数的区别

构造函数与普通函数唯一的区别就是调用的方式不同。除此之外,构造函数也是函数。任何函数只要使用new操作符调用就是构造函数,而不使用new操作符调用的函数就是普通函数。

注意:借助面向对象编程语言的特点,为区分构造函数和普通函数,构造函数的名称首字母都是要大写的,非构造函数则以小写字母开头。

1.new

通过构造函数创建对象,使用了new操作符。通过这种方式调用构造函数会执行以下操作:

内存中创建一个新对象这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的 prototype 属性构造函数内部的this 指向该新对象执行构造函数内部的代码(给新对象添加属性返回该新对象(如果构造函数返回非空对象的话)

当未使用new操作符调用,以普通函数的形式调用时,结果会将函数内部的属性和方法添加到window对象在没有明确设置this值的情况下,即作为对象的方法调用或者是使用call()、apply()调用),this始终指向Global对象(在浏览器中是window对象)

例如:

// 构造函数模式为对象定义属性和方法function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name);}}// 使用new操作符为构造函数创建对象let person = new Person("Nicholas", 29);person.sayName(); // Nicholas// 作为普通函数调用,添加到window对象Person("Greg", 27);window.sayName(); // Greg

此外:构造函数不一定要写出函数声明的形式,函数表达式也可以表示为构造函数

let Person = function(name, age) { // 函数表达式形式声明构造函数this.name = name;this.age = age;this.sayName = function () {console.log(this.name);}}let person = new Person("Nicholas", 29);person.sayName(); // Nicholas

2.new.target

new.target属性可用以检测一个函数是当做普通函数调用还是通过new关键字当做构造函数调用,前者new.target属性的属性值是undefined,后者new.target属性的属性值是指向构造函数的引用。

例如:

function Foo() {if(!new.target) throw "Foo must be called with new";console.log("Foo instantialted with new");}Foo(); // throws "Foo must be called with new"new Foo(); // Foo instantialted with new

三、使用构造函数

使用构造函数,意味所有的对象,都可以使用相同的基本结构创建

使用构造函数,意味着创建的对象被明确的标记为构造函数的实例

例如:

function Person(name, age) {this.name = name;this.age = age;}let person = new Person("Nicholas", 29);let people = {name: 'Jeck',age: 66}console.log(person instanceof Person); // trueconsole.log(people instanceof Person); // false

使用构造函数,意味着我们可以在原型上定义公共方法,供多个实例共享

例如:

function Person(name, age) {this.name = name;this.age = age;}// 原型上定义公共方法,供多个实例共享Person.prototype.getName = function() {return this.name;}let person_1 = new Person("Kevin Durant", 34);let person_2 = new Person("Kyrie Owen", 30);console.log(person_1.getName()); // Kevin Durantconsole.log(person_2.getName()); // Kyrie Owen

四、构造函数的问题

构造函数的主要问题在于:其内部定义的方法会在每个实例上都创建一遍,对于开头第一个例子而言,person_1和person_2两个对象都有名为sayName()的方法,但该方法却来自不同的实例,因此不同实例上的函数虽然同名,却不相等

function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name);}}let person_1 = new Person("Nicholas", 29);let person_2 = new Person("Greg", 27);console.log(person_1.sayName == person_2.sayName); // false

因此,因为都是做同一件事情,就无需重复创建不同的实例,要解决这个问题,可以把函数定义转移到构造函数外部去

例如:

function Person(name, age) {this.name = name;this.age = age;this.sayName = sayName;}function sayName() {console.log(this.name);}let person_1 = new Person("Nicholas", 29);person_1.sayName(); // Nicholaslet person_2 = new Person("Greg", 27);person_2.sayName(); // Greg

解析:在这里,sayName()被定义在了构造函数外部,在构造函数内部,sayName属性等同于全局sayName()函数,因为这次sayName属性包含的是一个指向外部函数的指针,所以person_1和person_2共享了定义在全局作用域上的sayName()函数。

总结

以上就是我对JavaScript构造函数的总结,希望对初学者能有帮助,如有不妥之处请批评、斧正。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。