-
Notifications
You must be signed in to change notification settings - Fork 52
框架设计
LYF edited this page Jun 12, 2018
·
40 revisions
var ZingTouch = {
_region:[], // 公共变量
Region: function(){
var id = ZingTouch._region.length;
console.log(id);
ZingTouch._region.push(obj);
}
}
var region = new ZingTouch.Region(); // 0
var region2 = new ZingTouch.Region();// 1
var region3 = new ZingTouch.Region();// 2
https://github.com/zingchart/zingtouch/blob/master/src/ZingTouch.js
var Trigger = function(_element) {
this.element = _element;
this.left = function(_this){
return function(){
return _this.element.left
}
}(this)
}
https://github.com/terwanerik/ScrollTrigger/blob/master/ScrollTrigger.js
var Trigger = function(_element){
this.element = _element;
var xoffset = 0; // 私有变量
var yoffset = 0; // 私有变量
}
https://github.com/terwanerik/ScrollTrigger/blob/master/ScrollTrigger.js
// 惰性函数
function CSPHack(array){
var a = array.reverse().join("")
return function(v){
return window[a].apply(0, v)
}
return window
}
var CSPcompile = CSPHack(["n","o","i","t","c","n","u", "F"])
// 类似于
// var f = Function.apply(0,['a','b','return a + b'])
// f(2, 3); // 5
function CSPcompile(array){
return Object.constructor.apply(0,array)
}
// 一个小技巧。由于与this相关,js引擎总能保证this是一个引用值,所以用call/apply方法时,context随便,第一个参数可写成0,比写成null要好
var $ = document.querySelectAll.bind(document);
var a = 12.3;
a |= 0;
console.log(a); // 12
a = -9.512;
a |= 0;
console.log(a); // -9
var arr = Array(10); // [undefined × 10]
arr[3] = 999;
arr[8] = void 0;
for(var i = 0, n = arr.length; i < n; i++){
if( i in arr ){
console.log(arr[i]); // 999, undefined
}
}
var isES5 = (function(){
"use strict";
return this === undefined;
})();
在bluebird中看到这种写法
var isES5 = (function(){
"use strict";
return this === undefined;
})();
if (isES5) {
module.exports = {
freeze: Object.freeze,
defineProperty: Object.defineProperty,
getDescriptor: Object.getOwnPropertyDescriptor,
keys: Object.keys,
names: Object.getOwnPropertyNames,
getPrototypeOf: Object.getPrototypeOf,
isArray: Array.isArray,
isES5: isES5,
propertyIsWritable: function(obj, prop) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
return !!(!descriptor || descriptor.writable || descriptor.set);
}
};
} else {
var has = {}.hasOwnProperty;
var str = {}.toString;
var proto = {}.constructor.prototype;
var ObjectKeys = function (o) {
var ret = [];
for (var key in o) {
if (has.call(o, key)) {
ret.push(key);
}
}
return ret;
};
var ObjectGetDescriptor = function(o, key) {
return {value: o[key]};
};
var ObjectDefineProperty = function (o, key, desc) {
o[key] = desc.value;
return o;
};
var ObjectFreeze = function (obj) {
return obj;
};
// 记住这个技巧:在try中进行运算,若发生了异常,在catch中返回
// 这样就在不支持或有问题的环境中,也能返回想要的结果
var ObjectGetPrototypeOf = function (obj) {
try {
return Object(obj).constructor.prototype;
}
catch (e) {
return proto;
}
};
// 记住这个技巧。catch中return
var ArrayIsArray = function (obj) {
try {
return str.call(obj) === "[object Array]";
}
catch(e) {
return false;
}
};
module.exports = {
isArray: ArrayIsArray,
keys: ObjectKeys,
names: ObjectKeys,
defineProperty: ObjectDefineProperty,
getDescriptor: ObjectGetDescriptor,
freeze: ObjectFreeze,
getPrototypeOf: ObjectGetPrototypeOf,
isES5: isES5,
propertyIsWritable: function() {
return true;
}
};
}
顺序是:self -> window -> global -> this -> null
var globalObject = typeof self !== "undefined" ? self :
typeof window !== "undefined" ? window :
typeof global !== "undefined" ? global :
this !== undefined ? this : null;
var obj = {b: 2};
Object.defineProperty(obj, 'a', {
enumerable: true,
configurable: true,
get: function(){
console.log(this); // {b: 2}
return 999;
},
set: function(v){
console.log(this); //{b: 2}
this.a = v; // 不能这样干,会栈溢出的
}
})
/*
将一个节点appendChild
它必须从原来的父节拔出
总是放在那个文档碎片中,会内存释放不了
这是不确定它有没有父节点,不知道父节点时的移除节点的方式
如果不知道这个节点的父节点,删除这个节点将会报错:
Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
*/
function removeNode(node){
var f = document.createDocumentFragment();
f.appendChild(node);
f.removeChild(node);
return node;
}
/**
* 一个节点如果放到文档碎片中,那么就会从页面删除
*/
function node2Fragment(node, vm) {
//这里是dom劫持,vue会新建一个文档片段来替换dom中本来的结点
var flag = document.createDocumentFragment();
//子节点
var child;
while (child = node.firstChild) {
console.log('child:', child)
//开始编译每个结点
// compile(child,vm);
//appendchild方法会自动删除node对象的child结点
flag.appendChild(child)
}
return flag;
}
作用:
1、深拷贝一个对象
2、干掉obj中的所有function
如果深拷贝时,需要带上所有function属性,那么就不能使用这种方式了。
这个技巧很好用。是在vue中看到的。也可以举一反三,进行任意转化。
var strArr = ['1','2','3'];
var numArr = strArr.map(Number);
在开发全屏查看组件时的心得,全屏查看组件目前有2个功能:
- 全屏查看
- 图片懒加载
这2个功能点要做好区分,不要耦合,这样再改全屏查看的功能时,不会影响图片懒加载的功能
若耦合在一起的话,修改全屏查看,极大可能会导致图片懒加载功能出错,需要重新测试图片懒加载功能。
要在方法层面遵循单一职责原则,这样在改代码时,改一个单一职责的方法比改大杂烩方法方便容易的多了,也不容易出错!!
var oEvent = {};
(function(){
var addEvent = function(){ /*代码的实现省略了*/ };
function removeEvent(){}
oEvent.addEvent = addEvent;
oEvent.removeEvent = removeEvent;
})();
// 实现连乘
function count(x){
var fn = function(y){
return count(x*y);
}
fn.toString = function(){ // 前面的还好理解,关键是这句话。
return x;
};
return fn;
}
alert(count(1)(3)(5)); // 15
注意一个小技巧,如果判断一个类型为一组类型中的某个,则可以用/null|object|boolean/.test(type)
function flatChildren(array, ret) {
ret = ret || []
for (var i = 0, n = array.length; i < n; i++) {
var el = array[i]
var type = typeof el
if (!el && /null|object|boolean/.test(type)) {
continue
}
if (/number|string/.test(type)) {
if (el === '') {
continue
}
if (ret.merge) {
ret[ret.length - 1] += el
} else {
el = String(el)
ret.push(el)
ret.merge = true
}
} else if (Array.isArray(el)) {
flatChildren(el, ret)
} else {
ret.push(el)
ret.merge = false
}
}
return ret
}
var promises = [], ar, br
function getNextEvent(){
return promises.shift()
}
promises.push(new Promise(function(r){
ar = r
}), new Promise(function(r){
br = r
}))
document.addEventListener("touchstart", function(e){
ar(e)
promises.push(new Promise(function(r){
ar = r
}))
})
document.addEventListener("mousedown", function(e){
br(e)
promises.push(new Promise(function(r){
br = r
}))
})
const readFileAsync = async function () {
while(promises.length){
let e = await getNextEvent()
console.log(e.type)
}
}