注意篇
定时器的匿名函数
虽然很方便, 建议用具名的, 因为维护好
setTimeout(function goHome(){
// 5s后跳转首页
}, 5000)
技巧篇
自执行函数的偷懒命名
;(function(win, ngr, ltn, doc, $body) {
})(window, navigator, location, document, document.body);
函数名提升比变量名优先级高
foo()
var foo;
function foo(){
alert(1)
}
模块机制
var modules = (function() {
var names = {}
return {
define(name, deps, callback) {
// 直接复用deps数组, 不用构建新的数组
deps.forEach((item,i) =>{
deps[i] = names[item]
})
names[name] = callback.apply(callback, deps)
},
get(name) {
return names[name]
}
}
})();
modules.define('bar', [], function(bar){
return {
barHi(){
alert('barHi');
}
}
})
modules.define('jquery', ['bar'], function(bar){
return {
hello(){
alert('Hello');
}
}
})
console.log(modules.get('jquery'))
try/catch块级作用域
try {
throw 1
} catch (a) {
a = 'test';
}
// error
console.log(a)
混入
//显式
var object = {
name: 1
}
// 混入
function mixin(src, target) {
Object.keys(src).forEach(item => {
// 不能覆盖target上的item
if(!(item in target)) {
target[item] = src[item]
}
})
return target
}
console.log(mixin(object, {
name: 22
}));
// 隐式混入
var testObject1 = {
name: 22,
getName(){
console.log(this.name);
}
}
var testObject2 = {
name: 333,
getName(){
testObject1.getName.call(this)
}
}
testObject2.getName()
寄生继承
function Vehicle() {
this.name = 'test'
}
Vehicle.prototype.getName = function () {
console.log(this.name);
}
function Dog() {
// 重点内容
var test = new Vehicle()
var getName = test.getName
test.getName = function () {
getName.call(this)
console.log('good ');
}
return test
}
Dog().getName()
维护代码继承
// ES5
function Button() {
}
Button.prototype.render = function () {
console.log('Button');
}
function NewButton() {
}
NewButton.prototype = Object.create(Button.prototype)
NewButton.prototype.render = function () {
Button.prototype.render.call(this)
console.log('New');
}
new NewButton().render()
// ES6
var Button = {
init() {
console.log('init');
}
}
var Button2 = Object.create(Button)
Button2.init = function () {
Button.init.call(this)
console.log('init2');
}
Button2.init()
语法篇
模块
// js/bar.js
export default {}
// index.html
<script type="module">
// 用相对/绝对路径/远程
import bar from './js/bar.js';
</script>
迭代器
数组内置迭代器, 可以直接用for…of语法
鸡肋篇
Object.getOwnPropertyDescriptor(object, key)
获取对象上属性的描述符, 包含 value, writable, enumerable, configurable
Object.defineProperty(object, key, config)
加强版定义对象的属性和值
config属性包含 value, writable, enumerable, configurable
Object.preventExtensions(object)
禁止对象增加新的属性
Object.seal(object)
调用了preventExtensions, 然后把所有属性的configurable改为false
Object.freeze(object)
调用了 seal, 然后把所有属性的writable改为false
in 和 testObj.hasOwnProperty(key)
in会查找原型链
hasOwnProperty只会查找自己
getter setter
function getter1() {
var object = {}
Object.defineProperty(object, 'dd', {
get() {
return 1
},
// 能被for...in 和 Object.keys(object)获取
enumerable: true,
})
}
function getter2(){
var object = {
name: 'test',
get a(){
return this.name;
},
set a(v){
this.name = v
}
}
}
原型检查
/*
1. instanceof
2. isPrototypeOf
3. isRelatedTo()
4. Object.getPrototypeOf(object)
5. 兼容__proto__
*/
function Test() {}
function Foo() {}
Foo.prototype = Object.create(Test.prototype)
Foo.prototype.test = function () { }
function Bar() {}
Bar.prototype = Object.create(Foo.prototype)
// 1. Bar对象的proto是否指向Foo.prototype
new Bar() instanceof Foo
// -----------------------
// 3. 这个函数来确认Object.create的继承关系
function isRelatedTo(o1, o2){
function F(){}
F.prototype = o2;
return o1 instanceof F;
}
var bar = {
name: 2
};
var newBar = Object.create(bar)
var newBar2 = Object.create(newBar)
console.log(isRelatedTo(newBar2, bar));
// 2. isPrototypeOf
// 内置的isRelatedTo
bar.isPrototypeOf(newBar)
// 4. 获取原型
Object.getPrototypeOf(Foo)
// 5. 兼容
Object.defineProperty(Object.prototype, '__proto__',{
get(){
return Object.getPrototypeOf(this)
},
set(o){
Object.setPrototypeOf(this, o)
return o
}
})
Object.create
// 兼容
Object._create = function(obj){
function F(){}
F.prototype = obj
return new F()
}
// 参数2是配置对象的属性
Object.create(a,{
name:{
enumerable: false
}
})