JavaScript构造函数 (2)

当我们创建一个函数时,该函数就会具备一个prototype属性,这个属性指向通过构造函数创建的那个函数的原型对象。通俗点讲原型对象就是内存中为其他对象提供共享属性和方法的对象。

所有的对象都有一个原型对象prototype,原型对象中有一个constructor属性指向包含prototype属性的函数,当我们访问一个对象中的属性时,首先会询问实例对象中有没有该属性,如果没有则继续查找原型对象。

在原型模式中,不必再构造函数中定义实例属性,可以将属性信息直接赋予原型对象:

function Person() { } Person.prototype = { name: ‘jiang’, job: ‘student’, sayName: function() { console.log(this.name) } } var person1 = new Person()

通过对原型对象模式的初步了解,我们发现所有的实例对象都共享相同的属性,这是原型模式的基本特点,但往往对于开发者来说这是把“双刃剑”,在实际开发中,我们希望的实例应该是具备自己的属性,这也是在实际开发中很少有人单独使用原型模式的主要原因。

将信息直接添加到原型对象上。使用原型的好处是可以让所有的实例对象共享它所包含的属性和方法,不必在构造函数中定义对象实例信息。

不过这种方式还是不够好,应为constructor属性默认是不可枚举的,这样直接设置,它将是可枚举的。所以可以时候,Object.defineProperty方法

Object.defineProperty(Person.prototype, ‘constructor’, { enumerable: false, value: Person })

方法四

这是使用最为广泛、认同度最高的一种创建自定义类型的方法。它可以解决上面那些模式的缺点。

在实际开发中,我们可以使用构造函数来定义对象的属性,使用原型来定义共享的属性和方法,这样我们就可以传递不同的参数来创建出不同的对象,同时又拥有了共享的方法和属性。

使用此模式可以让每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用

function Person(name) { this.name = name this.friends = [‘Shelby’, ‘Court’] } Person.prototype.sayName = function() { console.log(this.name) } var person1 = new Person() var person2 = new Person() person1.friends.push(‘Van’) console.log(person1.friends) //[“Shelby”, “Court”, “Van”] console.log(person2.friends) // [“Shelby”, “Court”] console.log(person1.friends === person2.friends) //false

方法五

动态原型模式将所有信息都封装在了构造函数中,初始化的时候,通过检测某个应该存在的方法时候有效,来决定是否需要初始化原型

function Person(name, job) { // 属性 this.name = name this.job = job // 方法 if(typeof this.sayName !== ‘function’) { Person.prototype.sayName = function() { console.log(this.name) } } } var person1 = new Person(‘Jiang’, ‘Student’) person1.sayName()

只有在sayName方法不存在的时候,才会将它添加到原型中。这段代码只会初次调用构造函数的时候才会执行。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzsff.html