JavaScript Patterns 读书笔记(二)
二.Object
Object Constructor Catch// Warning: antipatterns ahead// an empty objectvar o = new Object();console.log(o.constructor === Object); // true// a number objectvar o = new Object(1);console.log(o.constructor === Number); // trueconsole.log(o.toFixed(2)); // "1.00"// a string objectvar o = new Object("I am a string");console.log(o.constructor === String); // true// normal objects don't have a substring()// method but string objects doconsole.log(typeof o.substring); // "function"// a boolean objectvar o = new Object(true);console.log(o.constructor === Boolean); // true?Constructor’s Return Values
var Objectmaker = function () {// this `name` property will be ignored// because the constructor// decides to return another object insteadthis.name = "This is it";// creating and returning a new objectvar that = {};that.name = "And that's that";return that;};// testvar o = new Objectmaker();console.log(o.name); // "And that's that"?? ?As can you see, you have the freedom to return any object in your constructors, as long as it’s an object. Attempting to return something that’s not an object (like a string or a boolean false, for example) will not cause an error but will simply be ignored, and the object referenced by this will be returned instead(!).
function Waffle() {if (!(this instanceof Waffle)) {return new Waffle();}this.tastes = "yummy";}Waffle.prototype.wantAnother = true;// testing invocationsvar first = new Waffle(),second = Waffle();console.log(first.tastes); // "yummy"console.log(second.tastes); // "yummy"console.log(first.wantAnother); // trueconsole.log(second.wantAnother); // true?Array Constructor Curiousness
// an array of one elementvar a = [3];console.log(a.length); // 1console.log(a[0]); // 3// an array of three elementsvar a = new Array(3);console.log(a.length); // 3console.log(typeof a[0]); // "undefined"?
// using array literalvar a = [3.14];console.log(a[0]); // 3.14var a = new Array(3.14); // RangeError: invalid array lengthconsole.log(typeof a); // "undefined"? To avoid potential errors when creating dynamic arrays at runtime, it’s much safer to stick with the array literal notation.
console.log(typeof [1, 2]); // "object"?? Although this behavior makes sense (arrays are objects), it’s not too helpful. Often you?need to know if a value actually is an array. Sometimes you can see code checking for?the presence of length property or some array method such as slice() to determine “array-ness.” But these checks are not robust because there’s no reason why a nonarray?object shouldn’t have properties and methods with the same names. Also people sometimes?use instanceof Array, but this check works incorrectly when used across frames?in some IE versions.?ECMAScript 5 defines a new method Array.isArray(), which returns true if the argument?is an array. For example:
Array.isArray([]); // true// trying to fool the check// with an array-like objectArray.isArray({length: 1,"0": 1,slice: function () {}}); // false? ?If this new method is not available in your environment, you can make the check by calling the Object.prototype.toString() method. If you invoke the call() method of toString in the context of an array, it should return the string “[object Array]”. If the context is an object, it should return the string “[object Object]”. So you can do something like this:
if (typeof Array.isArray === "undefined") {Array.isArray = function (arg) {return Object.prototype.toString.call(arg) === "[object Array]";};}?Error Objects
try {// something bad happened, throw an errorthrow {name: "MyErrorType", // custom error typemessage: "oops",extra: "This was rather embarrassing",remedy: genericErrorHandler // who should handle it};} catch (e) {// inform the useralert(e.message); // "oops"// gracefully handle the errore.remedy(); // calls genericErrorHandler()}???? The error constructors invoked as functions (without new) behave the same as?constructors (with new) and return the same error objects.