JS注意事项 | 8月更文挑战

201 阅读3分钟

1,JS循环

1,遍历数组,20年前JavaScript刚萌生的时候,实现遍历的方法:

function eachArray(myArray) { 
   for(var index = 0; index < myArray.length; index++){ 
      console.log(myArray[index])
      } 
    } 
/* 20年之前的for循环写法*/ var myArray = [1,2,3,4,5,5,6] eachArray(myArray)

自ES5发布之后,可以使用内建方法:forEach

/* ES5的写法*/ 
   myArray.forEach(function(value) { 
    console.log(value)
  })

这样写的缺点是:不能使用break语句,也不能使用return语句返回到外层

有很多人尝试用for-in 循环:比如:

for(var index in myArray){
  console.log(myArray[index])
}

但是:千万不要这样做,有很大的问题存在

切记: (1)index是字符串,不是number类型

(2)for-in是为遍历对象而设计的,不适应数组的遍历

ES6最强大的集合遍历方法是:for-of

for-of可以遍历:数据,类数组,Set集合,Map集合,不支持普通对象的遍历

/*ES6的写法*/ 
  for(var value of myArray) {
     console.log(value)
    } 
 /* for-of不仅可以遍历数组还可以遍历字符串*/ 
 for(var chr of "abcdefg") { 
    console.log(chr) 
 } 
 /* for-of还可以遍历set,map对象*/ 
 var words = ['a', 'b', 'c', 'd', 'a', 'a']
 var uniqueWords = new Set(words)
 for(var word of uniqueWords) { 
 console.log(word) }
 /* map对象需要解构成键值对形式*/ 
 var phone =[ ["a", 1], ["b", 2], ["c", 3] ] 
 var phoneMap = new Map(phone) 
  for(var [key, value] of phoneMap) { 
    console.log('key=' + key, 'value=' + value)
}

普通对象的遍历方法:

/*for-of不支持普通对象循环,对象的循环用for-in 或者 Object.keys()*/ 
  for(var key of Object.keys(someObject)) { 
   console.log(key + ':' + someObject[key]) 
 }

2, JS 变量

1,关于定义变量

(1)之前:var a=12;

作用域: 全局 , 函数作用域

(2)ES6中 新增 块级作用域

let 注意:

1,没有预解析,不存在变量提升

2,在代码块内,只用let定义变量,在之前使用,都是报错,即 先定义完,在使用

3,相当于之前的var 没有变量提升,同一个代码库中,不支持重复定义

4,for循环,for循环里面是父级作用域,

const 常量,定义好了,不能改变

const arr = Object.freeze(['zlm','orgin']);

(3)立即执行函数 IIFE

之前:(function(){})();

现在: {};

建议:以后再不要var 了

2,解构赋值

(1) 非常有用,特别是在做数据交互,ajax

let [a,b,c]=[1,3,5]; 注意:左右两边,结构格式要保持一致

解构可以取别名[name:n]

解构可以赋默认值[a,b,c="暂无数据"]=[1,3];

3,字符串模板:

优点:可以随意换行

这个是趋势${name}

新增字符串查找: 以前用indexOf();返回索引位置和 -1比较

includes();返回true/false
if(navigator.userAgent.includes('Chrome')){
  alert("是Chrome");
}else{
  alert("不是Chrome");
}

startsWith(检测的东西);//是否以谁开头

endsWith(检测的东西);//是否以谁结尾

repeat(次数)重复字符串

padStart(整个字符串长度,填充的东西);字符串头填充,padEnd();字符串尾填充

4,函数

(1)函数可以给默认值了

function({x=0;y=0}={}){
  console.log(x,y);
}

(2)函数的参数默认是已经定义了,不能再使用let,const声明了

(3)扩展运算符,rest运算符 ...

排序

function show(){
return Array.prototype.slice.call(arguments).sort(function(a,b){
    return a-b;
});
}

新的方法:

function show2(...a){
 return a.sort();
}
let arr2 = [...arr1];

剩余参数:必须放到最后 (4)箭头函数 => () =>{ }

1,箭头函数中的this问题,指定义函数所在的对象,不再是运行时所在的对象

2,箭头函数里面没有arguments,但是有...

3,箭头函数不能当做构造函数

5,数组

arr.forEach(function(value,index,arr){
  console.log(value,index,arr)
})
let b=arr.some((val,index,arr)=>{
 return val=='orange'
});

以前: forEach() 循环之后没有返回值

map() 有返回值 ,返回新的数组

正常情况下,需要配合return 返回一个新的数组,若是没有return,相当于forEach,

注意:平时只要用map,一定是要有return,

filter() return 为true,数据保留下来 ,如果回调函数返回true,就留下来

some() 类是查找,数组里面某一个元素符合条件,返回true

every() 数据里面所有的元素都符合条件,才返回true

reduce() 和前面传递的参数不同,求数组的和,阶乘

let c = arr.reduce((pre,cur,index,arr)=>{
  return prv+cur;
})

reduceRight()

新增: for...of.

for(let val of arr){
 console.log(val);
}

for(let index of arr.keys()){
 console.log(index)
}

把类数组转换为数组的方法 Array.from(arr); [].slice.call(arr); 或者 [...arr]

类数组:只有具有length属性的都可以当做类数组处理

Array.of()把一组值转换成数组

arr.find():查找第一个符合的成员

arr.findIndex():找的位置

arr.fill(填充值,开始位置,结束位置):填充

arr.includes()包含

6,对象

JSON:对象简介语法

let json={
a:1,
b:2,
show:function(){
  }
}
Object.is(NaN,NaN) 判断两个东西是否相等
Object.assign()用来合并对象的 ,赋值一个对象,合并参数
let newObj = Object.assign({},json,json2)
Object.keys()
Object.values()
Object.entries()

解构:[keys,values,entries] = Object for(let value of values(json)){ } for(let key of keys(json)){ }

对象中也有... 扩展运算符

7,Promise 承诺,许诺

作用:解决异步回调函数

传统方式:大部分用回调函数,事件

let promise = new Promise(function(resolve,reject){}

本人用户:

new Promise().then(res=>{

    }).catch(res=>{

    });
Promise.sesolve('aa') :将现有的东西,转成一个promise对象,resolve状态,成功状态
new Promise(resolve=>{
    resolve('aa')
})

Promise.reject('aaa') :将现有的东西转成一个promise对象,reject状态,失败状态

Promise.all([p1,p2,p3]);把promise打包,扔到一个数组里面,打包完还是一个promise对象

必须确保,p1,p2,p3都是resolve状态

Promise.race([p1,p2,p3]):只要有一个成功了,就返回

3, 跨域CORS详解

CORS是W3C标准。全场跨域资源共享(Cross-origin resourse sharing)

她允许浏览器向跨域资源服务器放出XMLHttpRequest请求,克服了AJAX只能同源使用的限制

1,CORS通信是浏览器自动完成的,不需要用户参与。CORS通信和同源的AJAX通信没有差别,代码完全一样,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以通信

Access-Control-Allow-Origin:* (1) 为什么会有跨域的问题

浏览器安全的基石是:同源策略。什么是同源策略,简言之就是:请求的

协议相同 + 域名相同 + 端口号相同,只有在这三种情况都相同的情况下,才能 被称为同源策略。特别是在前后端分离开发的条件下,几乎跨域是一定会遇到的问题。

(2)CORS请求分成两类:简单请求和非简单请求

只有满足一下两大请求就属于简单请求:

(1)请求方法是以下三种方法之一:Head,get,post

(2) Http的头消息不能超出一下几种字段:

Content-Type:只限于三个值:application/x-www-form-urlencoded,(一般请求默认的方法) multipart/form-data,text/plain

除此之外:凡是不满足的都是非简单请求 (3)CORS请求流程

对于简单请求,浏览器直接发出CORS请求,并且在请求当前头信息中添加一个origin字段。origin其实就是(协议+域名+端口号),服务器根据这个值决定是否同意这次请求。

对于非简单请求,比如请求方法是put或者delete,或者Content-Type字段类型是application/json,,在正是请求之前会,服务器发现你是一个非简单请求,就会自动发出一个预检请求,预检请求的方法是OPTIONS,表示咨询。如果如服务器对预检请求的结果是允许跨域请求,就会第二次发出请求跨域请求。一旦服务器通过了预检请求,以后的每一次CORS请求都是简单请求了。

(5)CORS默认请求不会发送Cookie和HTTP认证信息的。如果要把Cookie发送到服务器,需要知道服务器同意:

Access-Control-Allow-Credentials:true

前端需要设置: widthCredentials = true

(4)CORS与JSONP的比较

CORS与JSON的目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSON的优势在与支持老式浏览器,可以向布置CORS的网站请求数据

注意:我们在使用POST方式是,JQuery,Axios等封装的Ajax库,都采用默认的

Content-Type:application/x-www-form-urlencoded,不会触发预请求

举例:处理POST预请求方法

前端发出请求,触发预请求

var data = { name: 'BruceLee', password: '123456' };
$.ajax({ 
    url: "http://localhost:3000", 
    type: "post",
    data: JSON.stringify(data),
    contentType: 'application/json;charset=utf-8',
    success: function (result) { 
       console.log(result); }, 
    error: function (msg) { console.log(msg); } })

服务器端要增加对OPTIONS得请求,比如node.js

const http = require('http');
const server = http.createServer((request, response) => { 
   if (request.url === '/') {
   if (request.method === 'GET') {
   response.writeHead(200, { 
   'Access-Control-Allow-Origin': '*' });
   response.end("{name: 'BruceLee', password: '123456'}"); } 
   if (request.method === 'POST') {
   response.writeHead(200, { 
   'Access-Control-Allow-Origin': '*' });
   response.end( JSON.stringify({state: true}) ); } 
   if (request.method === 'OPTIONS') {
   response.writeHead(200, { 'Access-Control-Allow-Origin': '*', 
   // 设置 optins 方法允许所有服务器访问 'Access-Control-Allow-Methods': '*', 
   // 允许访问路径 '/' POST等所有方法 'Access-Control-Allow-Headers': 'Content-Type', 
   // 允许类 Content-Type 头部 }); } }
   response.end('false'); });
   server.listen(3000, () => { console.log('The server is running at http://localhost:3000'); });

总结:使用CORS跨域资源共享,是需要分成预请求和非预请求处理的。

(1)非预请求:只需要在服务器端简单的数字:

'Access-Control-Allow-Origin': '*'

(2)预请求,在服务器内,至少需要设置三个响应首部字段:

(3)前端使用Content-Type:application/json的时候,必须注意,这是要发生预请求的,后端需要相对于的处理一下OPTIONS方法

4, JavaScript的异步加载

需求:之所以涉及到这个问题,主要因为和其他的公司联合开发一个项目,需要远程加载他们的JS,但又不能影响到我们的业务

方法:采用JS的远程异步加载方式

分析:浏览器在javaScript的加载中,分为三个方式:异步加载,同步加载,延迟加载,主要参考的属性:async,defer,

总结:(1)

同步模式,又称阻塞模式,会阻止浏览器的后续处理。这种模式,从上往下一次执行,如果js报错或执行缓慢,会阻止后续页面的渲染和代码执行

JS之所以要同步执行,是因为JS中可能要修改DOM或其他对页面操作的行为,所以,默认同步执行才是安全的

所以常常建议把之前,这样尽可能减少这种阻塞行为,而先让页面展示出来了

function loadScript(){
var script=document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("async",true);
script.setAttribute("src", "http://110.192.108.165:6260/4k/probe/stat.js?
stbNo=${EPG_USER_SESSION.userId}");
var heads = document.getElementsByTagName("head");
if(heads.length){
  heads[0].appendChild(script);
}else{
document.documentElement.appendChild(script);
 }
}

异步加载,又称非阻塞,浏览器在下载执行JS同时,还会继续进行后续页面的处理

(3)延迟加载可以通过setTimeout实现

网上方法太多,能实现自己的需求即可。

5, JSON转换

1,因为JSON使用的JavaScript语法,有内置的方法可以处理JSON数据

JSON的文本类型:application/json

JSON数据转换成JSON对象 eval();

JSON.parse(string);

2,JSON的读取方式两种: var x = Obj.name; var x = Obj['name']; 3,在使用for遍历JSON时,只能通过Obj['name']形式来获取属性值

4,JSON.parse(json,function(k,v){})

第二个参数是个函数,用来转换json的值

5,在向服务器发送数据的时候,同时是JSON字符串,需要把对象转换成JSON字符串

JSON.stringify(json对象);

6,JSONP 跨域问题

因为同源策略,ajax请求所产生的跨域问题。

JSONP:不支持Post请求

JSONP的原理:

(1)使用Script标签发送请求,这个标签支持跨域访问

(2)在Script标签里面给服务器端传递一个callback回调函数

(3)服务器端会把和这个calllback回调函数返还给页面,在全局作用域中选择callback函数,

(4)调用这个全局函数,并把数据作为参数传递到函数里面

JSONP只能用get请求