Home  >  Article  >  Web Front-end  >  A brief analysis of the pitfalls of JavaScript prototypal inheritance_javascript skills

A brief analysis of the pitfalls of JavaScript prototypal inheritance_javascript skills

WBOY
WBOYOriginal
2016-05-16 17:10:51894browse

JavaScript uses prototypal inheritance by default. Although there is no concept of a class, its function can act as a constructor. The constructor combined with this and new can build a Java-like class. Therefore, JavaScript can emulate class-based inheritance by extending itself.

JavaScript, like other object-oriented languages, uses references for object types. The variable holding the object is just an address, while the basic type data is the value. When storing objects on prototypes, there can be some pitfalls.

Look at the first example first

Copy the code The code is as follows:

var create = function() {
function Fn() {}
return function(parent) {
Fn.prototype = parent
return new Fn
}
} ()

var parent = {
name: 'jack',
age: 30,
isMarried: false
}
var child = create(parent)
console.log(child)

The create tool function implements a basic prototype inheritance. Each time create is called, a new object will be copied based on the parent object. All the properties of the new object come from the parent. . Here parent has three attributes, all of which are basic data types: string, number, and Boolean.

At this time, modify the child to see if it will affect the parent

Copy the code The code is as follows:

child.name = 'lily'
child.age = 20,
child.isMarried = true

console.log(child)
console.log(parent)

The results are as follows

That is, modifying the child will not affect the parent.

Look at another example

Copy the code The code is as follows:

var create = function() {
function Fn() {}
return function(parent) {
Fn.prototype = parent
return new Fn
}
}()

var parent = {
data: {
name: 'jack',
age: 30,
isMarried: false
},
language: ['Java']
}
var child = create(parent)

child.data.name = 'lily'
child.data.age = 20
child.data.isMarried = true
child.language.push('javascript')
console.dir(child)
console.dir(parent)

Note that the two attributes of parent here are data and language. They are reference types, one is an object and the other is an array. The child still inherits from the parent, and then the child is modified. The results are as follows

As you can see, the parent has also been modified at this time, and the name, age, etc. of the child are the same. This is something to be aware of when using prototypal inheritance.

A better way to use inheritance is:

1. Data attributes adopt class inheritance (hanging on this), so that new can also be configured through parameters

2. The method adopts prototypal inheritance, which can save memory. At the same time, overriding methods by subclasses will not affect the parent class

The following is a writing tool function that meets the above two points

Copy the code The code is as follows:

/**
 * @param {String} className
 * @param {String/Function} superCls
 * @param {Function} factory
 */
function $class(name, superClass, factory) {
if (superClass === '') superClass = Object
function clazz() {
if (typeof this.init === 'function') {
this.init.apply(this, arguments)
}
}
var p = clazz.prototype = new superCls
clazz.prototype.constructor = clazz
clazz.prototype.className = className
var supr = superCls.prototype
window[className] = clazz
factory.call(p, supr)
}

When the object type is placed on the prototype of the parent class, be careful when the subclass modifies it. In this case, all instances of subclasses inherited from the parent class will be modified. And the bugs caused by this are very difficult to find.

ES5 adds a new API to implement prototypal inheritance: Object.create. You can use it to replace the self-implemented create function above, as follows:

Copy the code The code is as follows:

var parent = {
name: 'jack',
age: 30,
isMarried: false
}
var child = Object.create(parent)
console.log(child )
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn