js使用技巧和常见问题汇总

ES5 和ES6【ES2015】规范

ES5是2009年的制定的规则,ES6是2015年制定,可以说比ES5有了一个非常大的突破。接下来我们主要说说ES6的特性。

1. let、const和块级作用域

	var 可以跨块访问,顶级window属性
	let   只能在块作用域访问,不可跨函数
	const 只能在块作用域访问,不可跨函数,声名时必须赋值,原始值不可修改
	//报错 const一旦声明就必须赋值
	const PI;
	//报错 const一旦声明如果值是原始类型的值,值不能改变
	const PI=3.1415926;PI = 3.14;
	//报错 const一旦声明如果值是引用类型的值,地址值不能改变
	const obj = {a:1,b:2}obj = {};

2.箭头函数(Arrow Function)

	//优点
	隐士返回,可省去return标识。解决this指向问题。写法简单。
	//不可用的地方
	构造函数。使用arguments对象。使用this处理点击对象的。

3. 模板字符串(Template String)

	//es5 插入大段的html内容到文档中
	$("div").append(
	  "There are <b>" + student.count + "</b> " +"students in your class ");
	//es6可以这样写
	$("#result").append(`
	  There are <b>${student.count}</b> students in your class。
	`);
对象字面量扩展语法(Enhanced Object Literals)

4.表达式结构:解构(Destructuring)

	let cat = 'andy'
	let dog = 'gary'
	let zoo = {cat, dog}  //传统写法 let zoo = {cat:cat, dog:dog}
	console.log(zoo)  //Object {cat: "andy", dog: "gary"}

5.default reset

	//es5
	function student(name){
	    name= name|| 'no';  
	    console.log(name);
	}
	student();
	//如果用ES6我们而已直接这么写:
	function student(name= 'no'){
	    console.log(name);
	}
	student();

6.函数参数表达、传参

	//es5 arguments 不是数组
	var f = function () {
	  console.log(arguments[0]);	//1
	  console.log(arguments[1]);	//2
	};
	f(1, 2);
	//es6 rest ...是数组,剩余不确定参数,可以和固定参数分离
	var f = function (count,...num) {
	  console.log(num[0]);	//2
	  console.log(num[1]);	//3
	  console.log(arguments[0],arguments[1],arguments[2],arguments.length);//1,2,3
	  count=5;
	  console.log(arguments[0]);//1 不会改变arguments原值
	};
	f(1, 2,3);

7.新的数据结构

	//Set 数组不重复,无序
	const s1 = new Set();
	s1.add(1);
	s1.add(2);
	s1.add(1);//{1, 2}
	s1.size //2
	s1.delete(2);//{1}
	s1.has(2);//false
	s1.clear();//清零
	for (let item of set.keys())for (let item of set.values());//效果一样
	
	//Set应用
	//1.数组去重 
	let array = [1,2,1,4,3,'1'];
	[...new Set(array)]     // [1, 2, 4, 3, "1"]
	//2.实现并集、交集、差集
	let a = new Set([1, 2, 3]);
	let b = new Set([4, 3, 2]);
	// 并集
	let union = new Set([...a, ...b]);// Set {1, 2, 3, 4}
	// 交集
	let intersect = new Set([...a].filter(x => b.has(x)));// set {2, 3}
	// 差集
	let difference = new Set([...a].filter(x => !b.has(x)));// Set {1}

	//WeakSet 较弱Set
	1.成员只能是对象,而不能是其他类型的值。
	2.没有size属性。
	3.不可循环。因为垃圾回收不考虑weakset的引用。
	4.优点是省内存,用完即被垃圾回收。
	
	//Map 键值对,代替object
	Map的键是跟内存地址绑定的,只要内存地址不一样,就视为两个键。键值是字符串,对象,甚至是一个函数。
	var map = new Map();
	var obj1 = ['m'];
	var obj2 = ['m'];
	map.set(obj1, 111);
	map.set(obj2, 222);
	map.get( obj1 );  //111
	map.get( obj2 );  //222
	
	map.has(obj1 )  // true
	map.delete(obj1 )  // true
	map.clear() //清除
	//map循环
	const map = new Map([['name', 'andy'],['age', 38]]);
	for (let key of map .keys()) {console.log(key)}
	// name
	// agefor (let value of map . values()) {console.log(value)}
	// andy
	// 38for (let item of map . entries()) {console.log(item[0], item[1])}
	// name andy
	// age 38
	​
	map .forEach((value, key) => console.log(key,value))
	// name andy
	// age 38
	
	//Map 转为 Array,使用扩展运算符 ...
	let map = new Map([['name', 'andy'], ['age', 38]]);
	[...map];  // 返回值为 [["name","andy"],["age",38]]
	
	//Array 转为 Map 数组必须是一个二维数组才可以
	let arr = [[1, 5], [1, 10], ['name', 'andy'], ['name', 'gary']];
	let map= new Map(arr);// 返回值为 Map(2) {1 => 10, "name" => "gary"}

	WeakMap
	
	WeakMap 与 WeakSet 作为一个比较新颖的概念,其主要特点在于弱引用,快速回收垃圾,减少内存占用量。

8.Promise
promise有三种状态: pendding fulfilled rejected

	如果是接受状态,则继续下一个then。如果是拒绝状态则直接停止。
	接受状态:调用resolve,或者返回一个值,或者无任何返回【传入参数会传到下一个then】
	拒绝状态:调用reject,或者抛出一个异常
    const promise = new Promise((resolve, reject) => {
	    // do something here ...
	    if (success) {
	        resolve(value); // fulfilled
	    } else {
	        reject(error); // rejected
	    }
	});
	
	//面试题1:红绿灯交替闪烁
	function red() {
	    console.log('red');
	}
	function green() {
	    console.log('green');
	}
	function yellow() {
	    console.log('yellow');
	}
	
	var light = function (timmer, cb) {
	    return new Promise(function (resolve, reject) {
	        setTimeout(function () {
	            cb();
	            resolve();
	        }, timmer);
	    });
	};
	//面试题1答案
	var step = function () {
	    Promise.resolve().then(function () {
	        return light(3000, red);
	    }).then(function () {
	        return light(2000, green);
	    }).then(function () {
	        return light(1000, yellow);
	    }).then(function () {
	        step();
	    });
	}
	
	step();
	
	//面试题2:要求分别输出 1  2   3  done  [1,2,3]
	const timeout = ms => new Promise((resolve, reject) => {
	    setTimeout(() => {
	        resolve();
	    }, ms);
	});
	
	const ajax1 = () => timeout(2000).then(() => {
	    console.log('1');
	    return 1;
	});
	const ajax2 = () => timeout(1000).then(() => {
	    console.log('2');
	    return 2;
	});
	const ajax3 = () => timeout(2000).then(() => {
	    console.log('3');
	    return 3;
	});
	const mergePromise = ajaxArray => {
	    // 在这里实现你的代码
	};
	mergePromise([ajax1, ajax2, ajax3]).then(data => {
	    console.log('done');
	    console.log(data); // data 为 [1, 2, 3]
	});
	//面试题2答案
	// 保存数组中的函数执行后的结果
	var data = [];
	
	// Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象。
	var sequence = Promise.resolve();
	
	ajaxArray.forEach(function (item) {
	    // 第一次的 then 方法用来执行数组中的每个函数,
	    // 第二次的 then 方法接受数组中的函数执行后返回的结果,
	    // 并把结果添加到 data 中,然后把 data 返回。
	    // 这里对 sequence 的重新赋值,其实是相当于延长了 Promise 链
	    sequence = sequence.then(item).then(function (res) {
	        data.push(res);
	        return data;
	    });
	})
	
	// 遍历结束后,返回一个 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data,
	// 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。
	return sequence;
	

Proxy

proxy翻译过来就是代理,对目标对象的外层搭建了一层拦截,外界对目标对象的一些操作【访问属性等】,可以进行某种需要的过滤。

	//代理对象
	var target = {
	   name: 'andy'
	 };
	 //代理对象的操作
	 var handler= {
	   get: function(target, key) {
	     console.log(`${key} 被读取`);
	     return target[key];
	   },
	   set: function(target, key, value) {
	     console.log(`${key} 被设置为 ${value}`);
	     target[key] = value;
	   }
	 }
	 //代理实例化
	 var proxy = new Proxy(target, handler);
	 
	 proxy .name; //输出:name 被读取
	 proxy .name = 'gary'; //输出:name 被设置为 gary
	 console.log(target.name); //输出: gary

Generator 生成器函数
function* 用来声明一个函数是生成器函数,比普通多了一个*。yield暂停交出执行权,next继续恢复执行权,可以理解为异步编程。

	function* test() {
	   console.log("this is generator");
	   //yield 代码会暂停
	   yield console.log("调用next 就往下执行一次");
	 }
	var h = test();//输出: 无
	h.next();//输出:this is generator
	h.next();//输出:调用next 就往下执行一次

代码模块化
commonjs 和 amd 规范:详细看这里

	ES5的代码模块化:
	1.common.js规范:
	同步加载,适合nodejs后端使用,通过module.exports定义模块
	
	2.AMD规范[Asynchronous Module Definition]:
	异步模块,适合浏览器前端使用,requrejs实现者,通过define方法,定义模块;通过require方法,加载依赖的模块。
	
	3.CMD规范:
	同步模块,SeaJS淘宝实现者,一个模块就是一个文件。
	

	ES6的代码模块化:
	通过export 定义模块,通过import 导入依赖模块。
	
	// student.js start
	let name = "andy";
	let age= 10;
	// score没有被导出,外界无法访问
	let score= 30;
	function info(){}
	
	// 将本模块中的私有成员 暴露出去,供其他模块使用,default只可有一个
	export default  {
	    name,
	    age,
	    info
	}
	// student.js end

	//test.js start
	// 导入模块成员
	import { name,age,info } from './student.js'
	console.log(name) // 输出: andy
	//test.js end

Symbol

	ES6数据类型有: Number 、 String 、 Boolean 、 Objec t、 null 和 undefined ,还新增了 Symbol。
 	Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
	Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。

	let student = {name:"andy"};
	//如果不小心这样写就覆盖上面的值了
	student.name = "gary";
	
	let student = {}
	let name = Symbol("name");
	let age = Symbol("name");
	
	console.log(name === age);//输出:false
	student[name]="andy";
	student[age]=18;
	

Web Worker 子线程

ES6引入的子线程概念,可以使用new Worker(url),将url指向的js代码,放入子线程中执行。

1.主线程 worker.html


<html>
<head>
	<title>ES6 子线程测试</title>
	<meta charset="UTF-8"/>
	<script>
		var myWorker = new Worker("my_task.js",{name:'andy'});
		//监听子域
		myWorker.onmessage =  (e)=> {
			console.log('%c%s','color:green','收到子域:',e.data);
			if(!e.data)return;
			let action = e.data.action;
			let param = e.data.param;
			switch(action){
				case "loadFile":
					myWorker.postMessage({action:"end",param:""}); 
				break;
			}
		};
		//异常处理
		myWorker.onerror=function (err) {
			console.log('%c%s','color:red',"主域收到异常:",err.message);
		}
		
		// 向子域发送信息
		myWorker.postMessage({action:"start",param:"info.txt"}); 
	</script>
</head>
</html>

2.子线程 task.js

    console.log("初始化子域:传入数据:",self.name);
	//监听主域
	self.addEventListener('message', (e)=> {
		console.log("收到主域:",e.data);
		if(!e.data)return;
		let action = e.data.action;
		let param = e.data.param;
        switch(action){
			case "start":
				loadFile(param);
			break;
			case "end":
				throw new Error('task is end!');
				//强行关闭子线程
				self.close();
			break;
		}
    }, false);
	
	function loadFile(fileName){
		var xmlreq = new XMLHttpRequest();
        xmlreq.responseType = "text";
        xmlreq.onload = function (e) {
            var data = e.currentTarget.response;
            self.postMessage({action:"loadFile",param:data});
        }
        xmlreq.open("get",fileName);
        xmlreq.send()
	}

基础学习

1.字符串替换 详细看这里

//替换字符串可以插入下面的特殊变量名:$$  $& 
"hello world".replace("h","9$&9");//输出 9h9ello world

2.前端错误信息监控 【详细看这里

window.addEventListener('error', function (e) {
    let logObj = {
        msg: e["error"] ? e["error"].message : "",
        errorObj: e["error"] && e["error"].stack ? e["error"].stack.toString() : ""
    }
});
//当Promise被reject且没有reject处理器的时候
window.addEventListener('unhandledrejection', function (e) {
    let logObj = {
        msg: e["reason"] ? e["reason"].message : "",
        errorObj: e["reason"] && e["reason"].stack ? e["reason"].stack.toString() : ""
    }
});

3.Object对象属性排序

	var obj={p120:{},p110:{},p50:{},p20:{}};
	//排序函数
	function objKeySort(obj) {
		//先对原对象属性名字排序
		var newkey = Object.keys(obj).sort((a,b)=>{
			if(Number(a.replace("p",""))<Number(b.replace("p","")))
				return -1;
			else
				return 1;
		});
	  //按照排序的名字,重新赋值到一个新对象
		var newObj = {};
		for (var i = 0; i < newkey.length; i++) {
			newObj[newkey[i]] = obj[newkey[i]];
		}
		return newObj;
	}
	obj=objKeySort(obj);
	//结果显示:p20  p50 p110 8120
	for(var key in obj){console.log(key)};

4.数学知识

//弧度和角度表示角的大小;正玄值,余玄值和正切值表示边与边的比例
/**
   * 角度转成弧度
   * @param angle 角度
   */
  public static angleToRadian(angle:number):number{
      return angle *Math.PI/180;
  }
  /**
   * 弧度转成角度
   * @param radian 弧度
   */
  public static radianToAngle(radian:number):number{
      return radian *180/Math.PI;
  }
  /**
  * 获得弧度
  * @param fromX 
  * @param fromY 
  * @param toX 
  * @param toY 
  * @return [-π,π]
  */
 public static getRadian(fromX:number,fromY:number,toX:number,toY:number):number{
     return Math.atan2(fromY-toY,fromX-toX);
 }

 //正玄值和余玄值 [-1,1]
 正玄:Math.sin(弧度值) = 对边/斜边
 余玄:Math.cos(弧度值) = 临边/斜边
 正切:Math.tan(弧度值) = 对边/临边
 //弧度  [-π/2,π/2]
 弧度:Math.asin(正玄值)
 弧度:Math.acos(余玄值)
 弧度:Math.atan(正切值)

浏览器方法

1.得到用户浏览器语言

function getBrowserLang(){
	var lang = navigator.languages? navigator.languages[0] : (navigator.language || navigator.userLanguage);
	lang = lang?lang.toLowerCase():"en";
	lang = lang.slice(0, 2)
	return lang;
}

2.得到用户浏览器类型

function getBrowser() {
    var u = navigator.userAgent;
    var bws = [{
        name: 'sgssapp',
        it: /sogousearch/i.test(u)
    }, {
        name: 'wechat',
        it: /MicroMessenger/i.test(u)
    }, {
        name: 'weibo',
        it: !!u.match(/Weibo/i)
    }, {
        name: 'uc',
        it: !!u.match(/UCBrowser/i) || u.indexOf(' UBrowser') > -1
    }, {
        name: 'sogou',
        it: u.indexOf('MetaSr') > -1 || u.indexOf('Sogou') > -1
    }, {
        name: 'xiaomi',
        it: u.indexOf('MiuiBrowser') > -1
    }, {
        name: 'baidu',
        it: u.indexOf('Baidu') > -1 || u.indexOf('BIDUBrowser') > -1
    }, {
        name: '360',
        it: u.indexOf('360EE') > -1 || u.indexOf('360SE') > -1
    }, {
        name: '2345',
        it: u.indexOf('2345Explorer') > -1
    }, {
        name: 'edge',
        it: u.indexOf('Edge') > -1
    }, {
        name: 'ie11',
        it: u.indexOf('Trident') > -1 && u.indexOf('rv:11.0') > -1
    }, {
        name: 'ie',
        it: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1
    }, {
        name: 'firefox',
        it: u.indexOf('Firefox') > -1
    }, {
        name: 'safari',
        it: u.indexOf('Safari') > -1 && u.indexOf('Chrome') === -1
    }, {
        name: 'qqbrowser',
        it: u.indexOf('MQQBrowser') > -1 && u.indexOf(' QQ') === -1
    }, {
        name: 'qq',
        it: u.indexOf('QQ') > -1
    }, {
        name: 'chrome',
        it: u.indexOf('Chrome') > -1 || u.indexOf('CriOS') > -1
    }, {
        name: 'opera',
        it: u.indexOf('Opera') > -1 || u.indexOf('OPR') > -1
    }];
 
    for (var i = 0; i < bws.length; i++) {
        if (bws[i].it) {
            return bws[i].name;
        }
    }
 
    return 'other';
}

3.得到用户系统

function getOS() {
    var u = navigator.userAgent;
    if (!!u.match(/compatible/i) || u.match(/Windows/i)) {
        return 'windows';
    } else if (!!u.match(/Macintosh/i) || u.match(/MacIntel/i)) {
        return 'macOS';
    } else if (!!u.match(/iphone/i) || u.match(/Ipad/i)) {
        return 'ios';
    } else if (!!u.match(/android/i)) {
        return 'android';
    } else {
        return 'other';
    }
}

4.全屏

launchIntoFullscreen: function () {
		element = document.getElementById("flashcontent");
		if (element.requestFullscreen) {
			element.requestFullscreen();
		} else if (element.mozRequestFullScreen) {//火狐
			element.mozRequestFullScreen();
		} else if (element.webkitRequestFullscreen) {//chrome
			element.webkitRequestFullscreen();
		} else if (element.msRequestFullscreen) {//ie11
			element.msRequestFullscreen();
		}
	},

	exitFullscreen: function () {
		if (document.exitFullscreen) {
			document.exitFullscreen();
		} else if (document.mozCancelFullScreen) {
			document.mozCancelFullScreen();
		} else if (document.webkitExitFullscreen) {
			document.webkitExitFullscreen();
		} else if (document.msExitFullScreen) {
			document.msExitFullScreen();
		} else if (document.msCancelFullScreen) {
			document.msCancelFullScreen();
		}
	}

cookie使用
检测浏览器是否支持:window.navigator.cookieEnabled

function setCookie(key,value,day){
    var cookie=key+'='+encodeURIComponent(value);
    if(day>0){
         var date=new Date();
         date.setDate(date.getDate()+day);
         cookie+=';expires='+date;
    }
    document.cookie=cookie;
}
function getCookie(key){
	if(document.cookie.indexOf(key)<0){ return ""; }
	var cookies=document.cookie.split(";");
	for(var i=0; i<cookies.length; i++){
		var temp=cookies[i].split("=");
		if(temp[0].replace(/\s/g,'')==key){
			return decodeURIComponent(temp[1]);
		}
      }
}
function deleteCookie(key){
	setCookie(key,'',-1);   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值