爲了方便計算,時常將在元素中設置font-size值爲62.5%javascript
var win_w=document.body.offsetWidth;
//定義變量
var fontSize;
if(win_w>640){
fontSize=24;
}else{
//若是瀏覽器窗口寬度(這裏的實質就是body寬度)值小於320,取320
win_w=Math.max(320,win_w);
fontSize=win_w/320*12
}
//設置根元素的大小
document.getElementsByTagName('html')[0].style.fontSize=fontSize+'px';
複製代碼
理想viewport寬度概括起來無非也就320、360、414css
請參考文章清除浮動的四種方法:html
BFC觸發方式:前端
bfc的做用:java
bfc處理:node
父級加:css3
子級加:git
參考文檔github
主要區別在於: content 的包含問題,IE盒子模型content包含padding border ,此時的寬度就是content的寬度 標準盒子模型:content不包含其餘任何部分。web
box-sizing:
6種原始數據類型:
引用類型:Object(Array 、Reg、 function等等)
類型 | typeof返回 |
---|---|
Undefined | undefined |
Null | object |
Boolean | boolean |
Number | number |
String | string |
Object | object |
Function | function |
instanceof: 用來判斷A 是不是 B的實例,表達式爲 A instanceof B,返回一個Boolean類型的值 instanceof 檢測的是原型,只能用來判斷兩個對象是否屬於實例關係, 而不能判斷一個對象實例具體屬於哪一種類型
Object.prototype.toString
console.log(Object.prototype.toString.call(123)); //[object Number]
console.log(Object.prototype.toString.call('123')); //[object String]
console.log(Object.prototype.toString.call(undefined)); //[object Undefined]
console.log(Object.prototype.toString.call(true)); //[object Boolean]
console.log(Object.prototype.toString.call({})); //[object Object]
console.log(Object.prototype.toString.call([])); //[object Array]
console.log(Object.prototype.toString.call(function(){})); //[object Function]
console.log(Object.prototype.toString.call(null)); //[[object Null]]
複製代碼
// call apply的實現https://blog.csdn.net/qq_40479190/article/details/78324270
Function.prototype.call = function(context){
var context = context || window;
context.fn = this;
var args = [...arguments].slice(1);
var result = context.fn(...args);
delete context.fn;
return result;
}
Function.prototype.apply = function(context){
var context = context || window;
context.fn= this;
var result;
if(arguments[1]){
result = context.fn(...arguments[1]);
}else{
result = context.fn();
}
delete context.fn;
return result;
}
Function.prototype.bind = function (context) {
var that = this;
return function(){
return that.apply(context);
}
}
Function.prototype.bind2 = function(context){
var that = this;
var args = Array.prototype.slice.call(arguments,1);//arguments不是真實的數組,因此不能直接調用slice方法,須要用這個方法
return function(){
var argslist = [...arguments];//第二參數是調用bind函數後返回的函數再調用的時候傳入的參數
return that.apply(context,[...args,...argslist]);//之因此也要用return是由於原函數可能有返回值
}
}
複製代碼
var fs = require('fs');
var readFile = function(fileName){
return new Promise((resolve, reject) => {
fs.readFile(fileName,(error, data) => {
if(error){
reject(error);
}else{
resolve(data);
}
});
});
}
var gen = function* (){
var f1 = yield readFile('/etc/sdfsdf');
var f2 = yield readFile('/etc/sdfsdf');
console.log(f1.toString());
}
var genFn = gen(); // 調用方法
genFn.next(); // {value:'sdfdf',done:true}
// 改寫成async函數
var asyncReadfile = async function(){
var f1 = await readFile('/etc/sdfsdf');
var f2 = await readFile('/etc/sdfsdf');
}
asyncReadfile();
複製代碼
async function fn(args){
// ...
}
//等同於
function fn(args){
return spawn(function* (){});
}// spawn爲自動執行器
function spawn(genF){
// genF爲generator函數
return new Promise((resolve, reject) => {
var gen = genF();// generator函數調用
function step(nextF){
// 封裝的執行器函數
try{
var next = nextF();
}catch(e){
return reject(e);
}
// 沒有返回錯誤判斷generator的返回結果
if(next.done){
// 若是next.done爲true表示generator已經執行完了
return resolve(next.value);
}
// 若是沒有執行完,則執行Promise.resolve(next.value)生成一個Promise對象而後繼續遞歸調用
Promise.resolve(next.value).then((v) => {
step(() => {
return gen.next(v);
});
}, (err) => {
step(() => gen.throw(e));
});
}
step(() => gen.next(undefined));
});
}
複製代碼
function compose(){
var args = arguments;
var start = args.length -1 ;
return function(){
var i = start;
var result = args[start].apply(this,arguments);
while (i--) result = args[i].call(this, result);
return result;
}
}
複製代碼
函數防抖:
在事件被觸發n秒後再次執行回調,若是在n秒內又被觸發,則從新計時(函數防抖就是法師發技能的時候要吟唱,技能讀條沒完再按技能就會從新讀條)
應用場景:
// 防抖debounce
// 初版
function debounce(func, wait){
var timeout;
return function(){
clearTimeout(timeout);
timeout = setTimeout(func, wait);
}
}
// this
function debounce(func,wait){
let timeoutNumber;
return function() {
let that = this;
clearTimeout(timeoutNumber);
timeoutNumber = setTimeout(function(){
func.applay(that);
},wait);
}
}
// 可能在執行的過程帶事件,因此須要傳遞參數
function debounce(func,wait){
var timeoutNumber;
return function() {
let args = arguments;
clearTimeout(timeoutNumber);
timeoutNumber = setTimeout(() => {
func.apply(this,args);
},await);
}
}
// 當即執行,一開始就執行下來
function debounce(func,wait, immediate) {
var timeout;
var result;
return function(){
var that = this;
var args = arguments;
if (timeout) {
clearTimeout(timeout);
}
if(immediate){
var callNow = timeout; // 有表示已經執行過了
timeout = setTimeout(() => {
timeout = null;
}, wait);
if(callNow){
result = func.applay(that,args);
}
} else {
timeout = setTimeout(() => {
result = func.applay(that,args);
}, wait);
}
return result; // 函數的返回值
}
}
// 取消
function debounce(func,wait, immediate) {
var timeout;
var result;
var debound = function(){
var that = this;
var args = arguments;
if (timeout) {
clearTimeout(timeout);
}
if(immediate){
var callNow = timeout; // 有表示已經執行過了
timeout = setTimeout(() => {
timeout = null;
}, wait);
if(callNow){
result = func.applay(that,args);
}
} else {
timeout = setTimeout(() => {
result = func.applay(that,args);
}, wait);
}
return result; // 函數的返回值
}
debound.cancel = function(){
clearTimeout(timeout);
timeout = null;
};
return debound;
}
複製代碼
函數節流:
規定在一個單位時間內,只能觸發一次函數,若是這個單位時間內觸發屢次函數,只有一次生效(我的理解:函數節流就是fps遊戲的射速,就算一直按着鼠標射擊,也只會在規定射速內射出子彈。)
// 利用時間戳來實現節流函數
function throttle(func,wait){
var previous=0;
var that = 0;
return function(){
var now=+ new Date();
args = arguments;
if(now - previous > wait){
func.apply(that, args);
previous = now;
}
}
}
const throttle2 = function(fn, delay) {
let preTime = Date.now()
return function() {
const context = this
let args = arguments
let doTime = Date.now()
if (doTime - preTime >= delay) {
fn.apply(context, args)
preTime = Date.now()
}
}
}
// 利用定時器來實現
function throttle(func,wait){
var timeout;
return function(){
var args = arguments;
if(!timeout){
timeout = setTimeout(() => {
time = null;
func.apply(this, args);
},wait);
}
}
}
const throttle = function(fn,delay) {
let timer = null
return function() {
const context = this
let args = arguments
if(!timer) {
timer = setTimeout(() => {
fn.apply(context,args)
clearTimeout(timer)
},delay)
}
}
}
//第三版
function throttle(func,wait){
var timeout,context,args,result;
var previous = 0;
var later = function(){
previous = + new Date();
timeout = null;
func.apply(context, wait);
}
return function(){
var now = + new Date();
var remaintime = wait - (now - previous);
context = this;
args = arguments;
if(remaintime <= 0 || remaintime > wait){
if (timeout){
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context,args);
} else if(!timeout){
timeout = setTimeout(later, remaintime);
}
}
}
function throttle(method, mustRunDelay) {
let timer,
args = arguments,
start;
return function loop() {
let self = this;
let now = Date.now();
if(!start){
start = now;
}
if(timer){
clearTimeout(timer);
}
if(now - start >= mustRunDelay){
method.apply(self, args);
start = now;
}else {
timer = setTimeout(function () {
loop.apply(self, args);
}, 50);
}
}
}
function throttle(fn,wait){
let timeout,
args,
start;
return function (){
args = arguments;
let that = this;
let now=Date.now();
if(!start){
start = now;
}
if(timeout){
clearTimeout(timeout);
}
}
}
複製代碼
let a = {
age: 1
}
let b = Object.assign({}, a);
a.age = 2;
console.log(b.age)// 1
複製代碼
let a = {
age: 1
}
b = {...a};
a.age = 2;
console.log(b.age);//1
複製代碼
// 數組的淺拷貝: slice concat方法能夠實現
function clone(arr){
var new_arr = arr.concat();
// var new_arr = arr.slice();
return new_arr;
}// 此方法只能拷貝沒有嵌套對象或者數組的
// JSON.stringify();可是不能拷貝函數
// 淺拷貝的實現
function shalloeCopy(obj){
if(typeof obj !== 'object'){
return;
}
var newObj = obj instanceof Array ? [] : {};
for (var i in obj){
console.log(i);
if(obj.hasOwnProperty(i)){
newObj[i] = obj[i]
}
}
return newObj;
}
shalloeCopy({sdf:2,sdfdfd:1});
// 深拷貝
function deepClone(obj){
if(typeof obj !== 'object'){
return;
}
var newObj = obj instanceof Array ? [] : {};
for(var key in obj){
if(obj.hasOwnProperty(key)){
// 防止原型鏈上的屬性
newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
}
}
return newObj;
}
複製代碼
function extend(){
var args = arguments;
var target = args[0];
var objs;
var newObj;
for(var i = 0; i<args.length;i++){
objs = args[i];
if(objs != null){
for(var name in objs){
target[name] = objs[name];
}
}
}
}
複製代碼
//偏函數 n 變成n-1元,只能一個個減小,m跟柯里化的區別
function partial(fn){
var args = [].slice.call(arguments, 1);
return function(){
var newArgs = args.concat([].slice.call(arguments));
return fn.applay(this,newArgs);
}
}
// 第二版
function partial(fn){
var args = [].slice.call(arguments,1);
return function(){
var position=0,len = args.length;
for(var i=0;i<len;i++){
args[i] = args[i] === _ ? arguments[position++] : args[i]
}
while(position < arguments.length) args.push(arguments[position++]);
return fn.apply(this, args);
}
}
// flatten扁平化
function flatten(){
let arr = arguments[0];
var result = [];
for(var i=0;i < arr.length;i++){
if(Array.isArray(arr[i])){
result = result.concat(flatten(arr[i]));
}else{
result.push(arr[i]);
}
}
return result;
}
// toString
function flatten(arr){
return arr.toString().split(',').map(item => +item);//+item是將字符串轉化成數字,可是數組中有字符串的不行
}
// reduce實現
function flatten(arr){
return arr.reduce(function(prev,next){
return prev.concat(Array.isArray(next)?flatten(next):next)
}, []);
}
複製代碼
// 初版
function curry(fn){
var args = [].slice.call(arguments, 1);//最外面的arguments,此處指的的是調用curry函數時候除了第一個函數外剩下的參數
return function(){
var newArgs = args.concat([].slice.call(arguments));//此處的arguments和前面的arguments不是一個,此處表示調用curry返回的函數再調用的時候又傳的參數
return fn.apply(this,newArgs);
}
}
function add(a, b) {
return a + b;
}
var addCurry = curry(add, 1, 2);
addCurry() // 3
//或者
var addCurry = curry(add, 1);
addCurry(2) // 3
//或者
var addCurry = curry(add);
addCurry(1, 2) // 3
// 第二版
function sub_curry(fn) {
var args = [].slice.call(arguments, 1);
return function() {
return fn.apply(this, args.concat([].slice.call(arguments)));
};
}
function curry(fn, length){
length = length || fn.length; // 判斷fn有多少形參
var slice = Array.prototype.slice; // arguments是非數組要調用該方法須要應用
return function(){
if(arguments.length < length){ // 表示調用柯里化後的函數參數沒有傳完
var combined = [fn].concat(slice.call(arguments)); // 柯里化後再調函數還須要的參數,與fn合成一個數組
return curry(sub_curry.apply(this, combined),length - arguments.length); // 總共須要的形參減去用過的形參
}else{
// 所調用的形參足夠直接調用
return fn.apply(this,arguments);
}
}
}
// 通用性 適用性 前幾個大量計算
// 1.參數複用性,
// http() https() get() getJson()
// 2。提早返回
var addEvent = function(el, type, fn ,capture){
if(window.addEventListener){
el.addEventListener();
}else{
el.atachEvent();
}
}
addEvent(p,click,callnack,true);
addEvent(p,click,callnack,true);
// 這樣前面的代碼調用了不少次
var addEvent = function(){
if(window.addEventListener){
return function(el, type, fn ,capture){
el.addEventListener();
}
}else {
return function(el, type, fn ,capture){
el.atachEvent();
}
}
}
var elBind = addEvent();
// 3.延遲執行 ,不定參數做爲最後一次調用(空間換時間)
var allScore = 0;
var addScore = function(score){
// 對分數的判斷 多少個三分 計算里程碑
allScore += score;
};
addScore(1);
addScore(2);
addScore(3); // 可是這樣每次就加了
// 虛擬緩存,代理緩存
var curryScore = function(fn){
var _allScore = [];
return function(){
if(arguments.length === 0){
// 表示統計了
return fn.apply(null, _allScore);
}else{
_allScore = _allScore.concat([].slice.call(arguments));
}
}
};
var curryAddScore = curryScore(function(){
for(var i=0;i<arguments.length;i++){
allScore+=arguments[i]
}
});
curryAddScore(1);//0
curryAddScore(2);//0
curryAddScore();//3 不傳參數的時候開始執行
複製代碼
function each(obj, callback){
var length,i=0;
if(isArrayLik(obj)){
length = obj.length;
for(;i<obj.length;i++){
let isOut = callback.call(obj[i],i,obj[i]);
if(isOut === false){
break;// 跳出循環
}
}
}else{
for (i in obj){
let isOut = callback.call(obj[i],i,obj[i]);
if(isOut === false){
break;
}
}
}
return obj;
}
複製代碼
// 第一種實現
function MyPromise(fn){
let self = this;
self.value = null;
self.error = null;
self.onFulfilled = null;
self.onRejected = null;
function resolve(value){
self.value = value;
self.onFulfilled(self.value);
}
function reject(err){
self.error = err;
self.onRejected(self.error);
}
fn(resolve,reject);
}
MyPromise.prototype.then = function(onFulfilled,onRejected){
this.onFulfilled = onFulfilled;
this.onRejected = onRejected;
}
module.exports = MyPromise;
複製代碼
// 改進方案
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(fn){
let self = this;
self.value = null;
self.error = null;
self.status = PENDING;
self.onFulfilled = null;
self.onRejected = null;
function resolve(value){
if(self.status === PENDING){
setTimeout(function(){
self.status = FULFILLED;
self.value = value;
self.onFulfilled(self.value);
});
}
}
function reject(error){
if(self.status === PENDING){
setTimeout(function(){
self.status = REJECTED;
self.error = error;
self.onRejected(self.error);
});
}
}
fn(resolve,reject);
}
MyPromise.prototype.then = function(onFulfilled, onRejected) {
if (this.status === PENDING) {
this.onFulfilled = onFulfilled;
this.onRejected = onRejected;
} else if (this.status === FULFILLED) {
//若是狀態是fulfilled,直接執行成功回調,並將成功值傳入
onFulfilled(this.value)
} else {
//若是狀態是rejected,直接執行失敗回調,並將失敗緣由傳入
onRejected(this.error)
}
return this;
}
複製代碼
const PENDING= 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(fn){
let self = this;
self.value = null;
self.error = null;
self.status = PENDING;
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value){
if(self.status === PENDING){
setTimeout(() => {
self.status = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach((callback) => {
callback(self.value)
});
},0);
}
}
function reject(error){
if(self.status === PENDING){
setTimeout(()=>{
self.status = REJECTED;
self.error = error;
self.onRejectedCallbacks.forEach((callback) => {
callback(slef.error);
});
},0);
}
}
fn(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
if(this.status === PENDING){
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}else if(this.status === FULFILLED){
onFulfilled(this.value);
}else {
onRejected(this.error);
}
return this;
}
複製代碼
function promiseAll(promises){
return new Promise(function(resolve, reject){
if(!(promises instanceof Array)){
throw new TypeError('promises must be an Array');
}
var len = promises.length;
var resolveCount = 0;
var resolvedArray = new Array(len);
for(var i=0;i<len;i++){
(function(i){
Promise.resolve(promises[i])
.then((value) => {
resolveCount++;
resolvedArray[i] = value;
if(resolveCount == len){
return resolve(resolvedArray);
}
},re => {
return reject(re);
}).catch((re) => {
console.log(re);
});
})(i)
}
});
}
複製代碼
// 數組去重
function unique(arr){
var res = [];
for(var i=0;i<arr.length;i++){
// 註明,此處能夠用數組方法includes 和indexOf方法來判斷
for(var j=0;j<res.length;j++){
if(arrp[j] == res[j]){
break;
}
if(j === res.length){
res.push(arr[i]);
}
}
}
return res;
}
// 排序後再去重
function unique(arr){
var res = arr.filter(function(item,index,arr1){
return arr.indexOf(item) === index;
});
return res;
}
function unique(arr){
var obj = {};
return arr.filter(function(item,index,arr1){
return obj.hasOwnProperty(typeof item + item) ? false : (obj[item] = true)
});
}
複製代碼
var ws;
var lockReconnect = false;
var wsUrl = 'ws:xxx.1.1.1';
function initEventHandle() {
ws.onclose = function() {
reconnet();
};
ws.onerror = function(){
reconnect();
};
ws.onopen = function() {
heartChect.reset().start();
};
ws.onmessage = function () {
heartChect.reset().start();
};
}
function reconnect(url){
if(lockReconnect){
return;
}
lockReconnect = true;
setTimeout(function(){
createWebSocket(url);
});
}
複製代碼