introduce
This article mainly introduces the next article of the pattern of creating objects. Using various techniques can greatly avoid errors or write very streamlined code.
Pattern 6: Function Syntax Sugar
Function syntax sugar is an extension to quickly add methods (functions) to an object. This mainly uses the characteristics of prototype. The code is relatively simple. Let's first look at the implementation code:
The code copy is as follows:
if (typeof Function.prototype.method !== "function") {
Function.prototype.method = function (name, implementation) {
this.prototype[name] = implementation;
return this;
};
}
When extending an object, you can use it like this:
The code copy is as follows:
var Person = function (name) {
this.name = name;
}
.method('getName',
function () {
return this.name;
})
.method('setName', function (name) {
this.name = name;
return this;
});
In this way, we add two methods: getName and setName to the Person function. Next, let’s verify the result:
The code copy is as follows:
var a = new Person('Adam');
console.log(a.getName()); // 'Adam'
console.log(a.setName('Eve').getName()); // 'Eve'
Pattern 7: Object Constant
Object constants are the embodiment of various methods provided by set, get, ifDefined in an object. Moreover, the set method will only retain the first object set, and the later setting will be invalid, which has achieved the purpose of others being unable to overload. The implementation code is as follows:
The code copy is as follows:
var constant = (function () {
var constants = {},
ownProp = Object.prototype.hasOwnProperty,
// Only these three types of values are allowed
allowed = {
string: 1,
number: 1,
boolean: 1
},
prefix = (Math.random() + "_").slice(2);
return {
// Set the property with name name
set: function (name, value) {
if (this.isDefined(name)) {
return false;
}
if (!ownProp.call(allowed, typeof value)) {
return false;
}
constants[prefix + name] = value;
return true;
},
// Determine whether there is a property named name
isDefined: function (name) {
return ownProp.call(constants, prefix + name);
},
// Get the attribute named name
get: function (name) {
if (this.isDefined(name)) {
return constants[prefix + name];
}
return null;
}
};
} ());
The verification code is as follows:
The code copy is as follows:
// Check if it exists
console.log(constant.isDefined("maxwidth")); // false
// Definition
console.log(constant.set("maxwidth", 480)); // true
// Retest
console.log(constant.isDefined("maxwidth")); // true
// Try to redefine
console.log(constant.set("maxwidth", 320)); // false
// Determine whether the original definition still exists
console.log(constant.get("maxwidth")); // 480
Mode 8: Sandbox mode
Sandbox mode provides a separate context for one or more modules without affecting the context of other modules. For example, there is a Sandbox with three methods event, dom, and ajax. If two of them are called to form an environment, there is no interference with the three environments. The Sandbox implementation code is as follows:
The code copy is as follows:
function Sandbox() {
// Convert parameters to array
var args = Array.prototype.slice.call(arguments),
// The last parameter is callback
callback = args.pop(),
// Except for the last parameter, all other modules to be selected
modules = (args[0] && typeof args[0] === "string") ? args : args[0],
i;
// Force the new operator
if (!(this instanceof Sandbox)) {
return new Sandbox(modules, callback);
}
// Add properties
this.a = 1;
this.b = 2;
// Add modules to this object
// If there is no module or the passed parameter is "*", then all modules are passed in
if (!modules || modules == '*') {
modules = [];
for (i in Sandbox.modules) {
if (Sandbox.modules.hasOwnProperty(i)) {
modules.push(i);
}
}
}
// Initialize the required module
for (i = 0; i < modules.length; i += 1) {
Sandbox.modules[modules[i]](this);
}
// Call callback
callback(this);
}
// Add prototype object by default
Sandbox.prototype = {
name: "My Application",
version: "1.0",
getName: function () {
return this.name;
}
};
Then we define the default initial module:
The code copy is as follows:
Sandbox.modules = {};
Sandbox.modules.dom = function (box) {
box.getElement = function () {
};
box.getStyle = function () {
};
box.foo = "bar";
};
Sandbox.modules.event = function (box) {
// access to the Sandbox prototype if needed:
// box.constructor.prototype.m = "mmmm";
box.attachEvent = function () {
};
box.detachEvent = function () {
};
};
Sandbox.modules.ajax = function (box) {
box.makeRequest = function () {
};
box.getResponse = function () {
};
};
The call method is as follows:
The code copy is as follows:
// Call method
Sandbox(['ajax', 'event'], function (box) {
console.log(typeof (box.foo));
// There is no dom selection, so box.foo does not exist
});
Sandbox('ajax', 'dom', function (box) {
console.log(typeof (box.attachEvent));
// There is no event selected, so the attachEvent defined in the event does not exist either
});
Sandbox('*', function (box) {
console.log(box); // All methods defined above are accessible
});
Through three different calling methods, we can see that the context of the three methods is different. The first one does not have foo; the second one does not have attachEvent, because only ajax and dom are loaded, but event is not loaded; the third one does not load everything.
Pattern 9: Static Members
Static Members are just static properties provided by a function or object, which can be divided into private and public, just like public static and private static in C# or Java.
Let's first look at public members. Public members are very simple. The methods and functions we declare usually are public, such as:
The code copy is as follows:
// Constructor
var Gadget = function () {
};
// Public static method
Gadget.isShiny = function () {
return "you bet";
};
// Normal method to add on the prototype
Gadget.prototype.setPrice = function (price) {
this.price = price;
};
// Call static methods
console.log(Gadget.isShiny()); // "you bet"
// Create an instance and call the method
var iphone = new Gadget();
iphone.setPrice(500);
console.log(typeof Gadget.setPrice); // "undefined"
console.log(typeof iphone.isShiny); // "undefined"
Gadget.prototype.isShiny = Gadget.isShiny;
console.log(iphone.isShiny()); // "you bet"
As for private static members, we can use their closure features to implement them. The following are two implementation methods.
The first implementation method:
The code copy is as follows:
var Gadget = (function () {
// Static variables/properties
var counter = 0;
// Closure returns a new implementation of the constructor
return function () {
console.log(counter += 1);
};
} ()); // Execute immediately
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
var g3 = new Gadget(); // logs 3
It can be seen that although it is a new object every time, the number is still incremented, achieving the purpose of static members.
The second method:
The code copy is as follows:
var Gadget = (function () {
// Static variables/properties
var counter = 0,
NewGadget;
//New constructor implementation
NewGadget = function () {
counter += 1;
};
// Authorize access to methods
NewGadget.prototype.getLastId = function () {
return counter;
};
// Overwrite constructor
return NewGadget;
} ()); // Execute immediately
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
The number is also incremented, which is achieved using the closure feature of its internal authorization method.
Summarize
This is the next article of the object creation mode. The two articles together have 9 patterns. They are the object creation modes that we often use in daily JavaScript programming. Different scenarios play different roles. I hope everyone will choose the applicable mode according to their respective needs.