类型判断:typeof,对象判断:instanceof
// bad
function add(a, b) {
return a + b;
}
// good
function add(a, b) {
a = typeof a === "number" ? a : 0;
b = typeof b === "number" ? b : 0;
return a + b;
}常见于 node 读取文件,网络操作。因为 JS 出错后,就会直接停止,不执行后面的方法。
try {
fs.readFile();
} catch (e) {
console.log(e.message);
}想要确定一个函数是不是被 new 关键字调用,也就是说这个函数是不是被作为构造函数而调用。
// bad
function Person(name) {
this.name = name;
}
// good
function Person(name) {
if (this instanceof Person) {
this.name = name;
} else {
throw new Error("必须用 new 关键字调用");
}
}
// better
function Person(name) {
if (typeof new.target !== "undefined") {
this.name = name;
} else {
throw new Error("必须用 new 关键字调用");
}
}
let person = new Person("Tim");
let notAPerson = Person.call(person, "Jim"); // 第二个不会抛出错误,第三种可以检测到错误保证一个类只有一个实例,提供全局访问。比如全局缓存、浏览器中的 window 对象只能有一个实例。
详见:设计模式之单例模式
继承:
function Parent() {}
Parent.prototype.func = function() {};
function Child() {
Parent.call(this);
}
Child.prototype = new Parent();
let _func = Child.prototype.func;
Child.prototype.func = function() {
_func.call(this);
// do something new
};组合:
function ParentFunc() {}
function ChildFunc() {}
function Child() {
ParentFunc();
ChildFunc();
}组合的优点在于低耦合,在继承中,如果父类型构造函数有修改,子类型就会跟着改变。所以能用组合就用组合,可扩展性强。
相同代码逻辑用一个方法,不同的部分当作享元来完成。
// bad
let button1, button2, button3;
button1.onclick = function() {
console.log("button1");
button1.style.color = "red";
};
button2.onclick = function() {
console.log("button2");
button1.style.color = "blue";
};
button3.onclick = function() {
console.log("button3");
button1.style.color = "green";
};
// good
let button1, button2, button3;
let arr = [
[button1, "button1", "red"],
[button2, "button2", "blue"],
[button3, "button3", "green"]
];
function action(word, color) {
console.log(word);
this.style.color = color;
}
arr.forEach(data => {
data[0].onclick = function() {
action.call(this, data[1], data[2]);
};
});框架里经常会用到这个方法,示例看:设计模式之装饰者模式
封装 axios 时做拦截器、过滤器常用,示例:设计模式之职责链模式
有一对多的事件方法要处理,示例:设计模式之观察者模式
示例:设计模式之策略模式