js是单线程,回调函数可以异步。(JS解释型语言,JAVA编译型语言)
编译型语言是在把所有代码编译完毕了,才执行
解释型语言是边解释变执行
JS
是由ES(ECMAScript)
、DOM
(浏览器文档对象)、BOM
(浏览器对象模型)组成。
其中Node.Js
就只有ES
,目前浏览器比较流行的版本就是ES6(ES2015)
,老浏览器的版本基本上都是ES5
。所以alert
和document
不能在Node
运行(因为Node
没有dom
和bom
)。
JavaScript 与 TypeScript 的关系(TypeScript 包含JavaScript)
TypeScript是Javascript的超集,实现以面向对象编程的方式使用Javascript。当然最后代码还是编译为Javascript。
TypeScript和ES6的关系(TypeScript 包含ES6)
TypeScript是ES6的超集。至于需不需要使用,在于你所需要的场景。比如在Angular2中,用TypeScript明显好于ES6。
1.数据类型
布尔,number,string,null,undefined,object
控制台颜色
蓝色是number型,黑色是字符型的
undefined,null是灰色
2.undefind和null区别
null表示"没有对象",即该处不应该有值
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
3.判断不同的数据类型
4.闭包,原型,原型链
5.js数组方法
forEach map 循环,sort排序,reverse 倒序,push添加对象,concat连接两个数组,splice,pop等等
6.js数组去重
7.es6新特性
let声明一个变量,const声明一个变量,作用于局部,
模板字符串
解构赋值
展开运算符
箭头函数
8.两个字符串,查重
9.通过递归或条件判断写一个函数重复输出一个字符串
浏览器内核分成两部分:渲染引擎和JS引擎。
渲染引擎:负责取得网页bai的内容(html,xml和图像等),整理du讯息(例如假如css),以及计算网页的显示方式,然后输出到显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎:解析和执行JavaScript来实现网页的动态效果。
浏览器本身并不会执行JS代码,而是通过内置JS引擎来逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以JavaScript为脚本语言,会逐行解释执行。
尽量不要用浮点数进行运算,不要拿两个浮动数进行比较
JS是单线程的,报错后,后面的代码就不执行了
鼠标经过事件onmouseover,鼠标离开事件onmouseout
(function(a,b){ return a; }(1,2)
var ipt = document.querySelector(’.ipt’);//选中元素给变量
ipt.onblur = function() {
message.className = ‘message wrong’;//message是元素类名,给它新增一个类名 wrong
}
document.style.backgroundImage = ‘url(’+ this.src+’)’;//给body换背景图片
e.target
1.排他思想(循环绑定事件)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kIkN2Agx-1641396761434)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201031102536894.png)]
1、执行顺序
JavaScript程序按照在HTML文档中出现的顺序逐行执行。如果需要在整个HTML文件中执行,最好将其放在HTML文件的标签中。某些代码,如函数体内的代码,不会被立即执行,只有当所在的函数被其他程序调用时,该代码才会被执行。
2、区分大小写
JavaScript是严格区分大小写的。例如str和Str这是两个完全不同的变量。
3、分号和空格
在JavaScript中,语句的分号“;”是可有可无的。但是我们强烈要求大家在每一句语句后面加一个分号“;”,这是一个非常重要的代码编写习惯。
另外,JavaScript会忽略多余的空格,用户可以向脚本添加空格,来提高代码的可读性,说白了就是让代码“漂亮点”,读得舒服一点。
例如:
12 | var str=``"绿叶学习网JavaScript教程"``;``var str = ``"绿叶学习网JavaScript教程"``; ``//这一行代码读起来舒服一点 |
---|---|
语法:
“//”是单行注释方式(ctrl+/),
“/****/”是多行注释方式(/**后按空格或者shift+alt+a(默认)改为ctrl+shift+/)
JavaScript对程序流程的控制跟其他编程语言是一样的,主要有3种:
(1)顺序结构;
(2)选择结构;
(3)循环结构;
在JavaScript中,选择结构共有5种:
(1)if语句;(2)if……else语句;(3)if……else if……语句;(4)if语句的嵌套;
(5)switch语句;
在JavaScript中,循环结构总有3种:
(1)while语句;(2)do……while语句;(3)for语句;
JavaScript支持的跳转语句主要有2种:
(1)break语句;(2)continue语句;
break语句与continue语句的主要区别是:break是彻底结束循环,而continue是结束本次循环。在这一点跟其他编程语言(如C和Java)相同。
console.log("嘿嘿嘿");
我们还能写console.warn("这是一个警告!");
或者 console.error("这是一个错误!");
可参考Console 对象document.write('你好吖~');
当然,这里除了写文字 还可以写标签document.write('我是Henry
');
,document.write('很高兴认识你~');
都是可以的,只要是文本都可以写入。window.prompt('你想和Henry说什么吖?');
和prompt('你想和Henry说什么吖?');
均可,不过它们是有一些区别的。window.onload = function ()
函数里的,通过window调用的会正常等待窗口内容全部加载完毕后再加载,而直接prompt()使用的会先加载,阻断网页内容的加载,这种情况建议直接写 window.prompt('你想和Henry说什么吖?');
)window.confirm('请做出你的选择');
标识(zhi)符:开发人员为变量,属性,函数,参数取的名字。
关键字:JS本身已经使用了的字,不能再用它们充当变量名,方法名。
保留字:实际上就是预留的“关键字”,意思是现在虽然还表示关键字,但未来可能会成为关键字,能使用它们当变量名或者方法名。
表达式:由变量,数字,运算符等组成的式子。如a++
先算完右边的再把返回值给左边。var num=1+1;
变量是程序在内存中申请的一块用来存放数据的空间。(存放数据的容器,通过变量名找到)。
变量使用:1.声明变量 2.赋值
var myname='十大 ';//注意字符串的要打单引号;
后面的会覆盖前面的,如果变量名相同的话。
声明多个变量,var后变量名用逗号隔开。
只声明未赋值,结果是undefined
不声明不赋值 直接使用,会报错 。
不声明直接赋值使用,可以。(qq=10;console.log(qq);)
由字母,数字,下划线,美元符号($),组成。(没有空格哦)
严格区分大小写
不能以数字开头
不能是关键字,保留字。
变量名必须有意义
遵守驼峰命名法。首字母小写,后面的单词的首字母需要大写,
推荐翻译网站:有道,爱词霸
尽量不要用name作为变量名,不然有时未声明未赋值,console.log(name);不报错
变量之间赋值后,数据会转移。当一个变量里面没有值的时候。
当两个变量都有值,赋值会报错,数据会覆盖。
js的数据类型是只有在程序运行过程中,根据等号左边的值来确定的
js是动态语言,变量的数据类型是可以变化的
全局变量:在全局作用域下的变量 在全局下都可以使用
注意:如果函数内部 没有声明直接赋值的变量 全局变量是
局部变量:在局部作用域下的变量 在函数内部的变量就是 局部变量
注意:函数的形参也是局部变量,局部变量只能在函数内部使用
从执行效率来看全局变量和局部变量
1.全局变量只有在浏览器关闭的时候才会销毁,比较占内存资源
2.局部变量 当我们代码块(程序)执行完毕就会销毁, 比较节约内存资源
js中前面加0表示八进制,前面加0x表示十六进制
数字型的最大值:Number.MAX_VALUE(1.7976931348623157e+308)
数字型的最小值:Number.MIN_VALUE(5e-324)
Infinity无穷大 -Inifinity负无穷大
NaN 非数字的 console.log(‘哈哈’-100);//字符串-字符型结果为NaN(Not a Numder),但是console.log(‘103’-100);//结果为3
isNaN()用来判断一个变量是否为非数字的类型,返回true或者false
用法: console.log(isNaN(useName));
JS推荐单引号。碰到引号嵌套(外双内单,外单内双)
字符串转义字符(包含在引号里面)
\n换行
\b空格
\t缩进
console.log(“我是\n程序员”);
length属性来判断字符串的长度
字符串的拼接(+),字符串+任何类型=拼接 之后的新字符串
+号总结口诀:字符串相加,字符相连
alter(‘100’+‘100’);//100100
alter(‘11’+12);//输出1112
console.log(‘pink’+18);//输出pink18
加强的地方引引加加(变换步骤如下)
console.log(“我18岁了”);
console.log(“我’'岁了”);
console.log(“我’++'岁了”);
console.log(“我’+age+'岁了”);
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
var str = ‘andy’;
console.log(str);
str = ‘red’;
console.log(str);
//因为我们字符串的不可变,所以不要大量的拼接字符串
var str = ‘’;
for(var i = 1; i < = 10000000000;i++) {str += i;}//数字月大越占内存
console.log(str);
true当1看,false当0看。参与和数字型向加。
如果一个变量声明未赋值,就是undefined;
var variable=undefined;
console.log(variable+‘pink’);//undefinedpink
console.log(variable+1);//NaN
var space=null;
console.log(‘哈哈’+space);//哈哈null
console.log(1+space);//1
console.log(true+space);//1
let sy = Symbol(“KK”); console.log(sy); // Symbol(KK) typeof(sy); // “symbol” // 相同参数 Symbol() 返回的值不相等 let sy1 = Symbol(“kk”); sy === sy1; // false
对象(object)
函数是一种特殊的对象
var str = ‘str’;
console.log(str.length);
//对象 才有属性和方法 复杂数据类型才有属性和方法
// 简单数据类型为啥会有length属性呢?
// 基本包装类型:就是把简单数据类型包装成复杂数据类型
// 步骤:
// (1)把简单数据类型包装成复杂数据类型
var temp = new String(‘andy’);
// (2)把临时变量的值给 str
str = temp;
// (3)销毁这个临时变量
temp =nulll;
Javascript提供三个特殊的引用类型:String,Number,和Boolean
console.log(typeof str);
var fn = function(){};
console.log(typeof(fn)); //‘function’
console.log(typeof(class c{})); //‘function’
链接:https://developer.ibm.com/zh/technologies/web-development/articles/1306-jiangjj-jsinstanceof/
var oStringObject = new String("hello world");
console.log(oStringObject instanceof String); // 输出 "true"
// 判断 foo 是否是 Foo 类的实例
function Foo(){}
var foo = new Foo();
console.log(foo instanceof Foo)//true
instanceof用法
1、检测某个对象是不是另一个对象的实例
2、判断继承关系中是不是父类
1.把数字型转换为字符串型 变量.toString() var str=num.toString();
2.利用String(变量)强制转换 console.log(String(num));
3.利用+拼接字符串的方法实现转换效果 隐式转换 console.log(num+’’);
1.parseInt(变量),只能转换为整数 ,碰到不是数字就返回
console.log(parseInt('3.14 '));//3
console.log(parseInt('120px '));//120
console.log(parseInt('rem120px '));//NaN
2.parseFloat(变量) ,可以 转换为字符型
console.log(parseFloat('3.14 '));//3.14
console.log(parseFloat(‘120px’));//120
console.log(parseFloat(‘rem120px’));//NaN
3.利用Number(变量)
var str=’123‘;
console.log(Number(str));//123
console.log(Number(‘12’));//12
4.利用算数运算- * / 隐式转换
console.log(‘12’-0);//12
console.log(‘123’-‘120’);//3
console.log(‘123’*1);//123
Boolean()函数。代表空,否定的值会被转换为false,如’’,0,NaN,undefined,null
其余的值都会被转换成ture
console.log(Boolean(’’));//false
console.log(Boolean(0));//false
console.log(Boolean(NaN));//false
console.log(Boolean(undefined));//false
console.log(Boolean(null));//false
+,-,*,/,%
console.log(0.1+0.2);//0.300000000000000004
注意算数运算符的优先级,
++写在变量的前面
先加1后返回值。
++写在变量的后面
先返回值后加1。
练习1
var c=10;
c++;//c++ 11 c=11 单独的后置递增和前置递增一样,与其他代码联用时结果就不同
var d=c++ + 2;//c++ = 11 c=12
console.log(d);//13
练习2
var e =10;
var f=e++ + ++e’;//1. e++ = 10 e=11 2.e=12 ++e=12
console.log(f);//22
开发时,大多数使用后置递增/减,并且代码单独占一行。
<, > , >= , <=
=赋值
==默认会转型(隐式转换),判断两边的数值是否相等
console.log(18 == ‘18’);//true
===全等,判断两边的值和数据类型完全相同
&&
||
!
除了0,’’,null,undefined,NaN为false,其他都为ture
逻辑与短路运算(逻辑中断)
如果表达式1为真 则返回表达式2 ,如果表达式1为假,则返回表达式1
console.log(123 && 456);//456
console.log(0 && 456);//0
console.log(’’ && 456 && 1+2 && 345);//’’
如果有空的或者否定的为假,其余都是真的,则返回0,’’,null,undefined,NaN
逻辑或短路运算(逻辑中断)
如果第一个表达式值为真,则返回表达式1
如果第一个表达式的值为假,则返回表达式2
var num=1;
console.log(12 || num++);//12 num++不执行
console.log(num);//1
=
+= -= ; var age = 10; age+=5;//15
=,/=,%= ;var age = 2; age=5;//10
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | () |
2 | 一元运算符 | ++ – ! |
3 | 算数运算符 | 先* / %后± |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | == != === != |
6 | 逻辑运算符 | 先&& 后|| |
7 | 赋值运输符 | = |
8 | 逗号运算符 | , |
1.利用new来创建数组(不常用)
var 数组名 = new Array();
var arr = new Array(); //创建一个新的空数组
2.利用数字字面量来创建数组[](使用最多)
var arr = [];//创建新的空数组
var arr1 = [ 1,2,‘是的’,ture];
存放在数组里面的数据叫数组元素。数组里面类型没有限制
索引从0开始
var arr = [‘red’, ‘green’,‘blue’,‘pink’];
var str = ‘’;
var sep = ‘|’;
for(var i = 0;i < arr.length; i++){
str += arr[i] + sep;//把数组中所有元素取出来,加到字符串里面
}
console.log(str);//red|green|blue|pink|
1.修改length长度
arrr.length=10;
2.可以通过修改索引号 追加数组元素
arr[4] = ‘hotpink’;//假设4号索引为空
不能直接给数组名赋值,否则会覆盖掉以前的数据
函数:就是封装了一段可以被重复执行调用的代码块。封装就是打包。
1)function声明函数关键字 全部小写
2)函数是做某件事,函数名一般是动词sayHi
3)函数不调用自己不执行。调用:函数名();
可以利用函数的参数实现函数重复不同的代码
function cook(aru){console.log(aru);}
cook(“csdn”);
函数的参数可以有也可以无,个数不限。
1.利用函数关键字自定义函数(命名函数)
function fn(){}
fn();
2.函数表达式(匿名函数)
var fun = function(){}
fun();
1.fun是变量名,不是函数名
2.函数表达式声明方式跟声明变量差不多,只不过变量声明的是值,而函数表达;里存的是变量
3.函数表达式也可以进行传参
如果实参的个数多于形参, 多的实参不会要,只取形参的个数
如果实参的个数小于形参的个数,多的形参定义为undefined,结果为NaN
函数的内部不应该有输出语句,应该返回值给调用者。
我们函数只是实现某种功能,最终的结果需要返回给函数的调用者。
只要函数遇到return 就把后面的结果返回给函数的调用者 函数名() = =return后面的结果
function getResult() {
return 666;
}
getResult();//getResult() = 666
console.log(getResult());//666
在实际的开发过程中,我们经常用一个变量来接收函数的返回结果
如:var re = getArrMax([3,77,55,99]);
return后面的代码不会被执行
return只能返回一个值。如果用逗号隔开多个值,以最后一个为准。
但是可以返回一个数组,就能返回多个值
return [num1 + num2,num1 - num2,num1 * num2,num1 / num2];
如果函数没有return返回的undefined
function fn(){
console.log(arguments);//123 里面存储了所有传递过来的实参
console.log(arguments[2]);
}
fn(1,2,3);
arguments是伪数组 并不是真正意义上的数组
1.具有数组的length属性
2.按照索引的方式进行存储
3.它没有真正数组的一些方法 pop() push()等等
作用域:就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突
全局作用域:整个script标签 或者是一个单独的js文件
局部作用域(函数作用域):在函数内部的就是局部作用域 这个代码的名字只是在函数内部起效果和作用
不同的作用域下不会起冲突,尽管命名相同
作用域链:内部函数访问外部函数的变量,采用的是链式查找(一层一层的往外找)的方式来决定那个值。遵循就近原值,找到最近的之后,就不查找了。
我们js引擎运行js分为两步:预解析 代码执行
1.预解析js引擎会把js里面所有的var还有function提升到当前作用域的最前面
2.代码执行 按照代码书写顺序从上往下执行
预解析分为 变量预解析 (变量提升)和函数预解析 (函数提升)
1.变量提升 就是把所有的变量声明提升到当前作用域的最前面 不提升赋值操作
console.log(num);
var num=10;
相当于以下代码,js所看到的是:
var num;//声明放到最前面,赋值没有变
console.log(num);
num=10;
案例4
f1();
console.log©; console.log(b); console.log(a);
function f1(){
var a = b = c = 9;
console.log(a); console.log(b); console.log©;
}
相当于
function f1(){
var a;
a = b = c = 9;//相当于var a = 9; b=9; c = 9;b和c没有直接赋值 没有var声明 当全局变量
//集体声明 var a = 9,b = 9; c = 9;
console.log(a); console.log(b); console.log©;
}
f1();
console.log©; console.log(b); console.log(a);
//输出结果为 9 9 9 9 9 undefined
2.函数提升 就是把所有函数声明提升到当前作用域的最前面 不调用函数
函数表达式 调用必须写在函数表达式下面
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串,数值,数组,函数等。
对象是由属性和方法组成。
属性:事物的特征,在对象中用属性来表示(常用名词);
方法:事物的行为,在对象中用方法来表示(常用动词);
**JS的对象表达结构 更清晰,更强大。**用数组保存会不清晰。
如person.name="张三;"person.sex=“男”;person.age=“128”;person.height=154;
//var obj = {};//创建了一个空的对象
var obj = {
uname:‘战神’,
age:‘18’;
sex:‘男’;
sayHi:function(){
console.log(“hi~”);
}
}
1)里面的属性或者方法我们采取键值对的形式, 键 属性名 :值 属性值
2)多个属性或者方法中间用逗号隔开
3)方法冒号后面跟的是一个匿名函数
2.使用对象
1)调用对象的属性 我们采取 对象名。属性名 我们理解的为
console.log(obj.uname);
2)调用属性还有一种方法 对象名[‘属性名’] 千万别忘记添加小括号
console.log(obj[‘age’]);
3)调用对象的方法sayHi 对象名.方法名()
obj.sayHi();
var obj = new Object();
obj.uname = ‘张三’;
obj.age = 18;
obj.sex = ‘男’;
obj.sayHi = function(){
console.log(‘hi~’);}
//我们是利用等号=赋值的方法 添加对象的属性和方法
//每个属性和方法之间用分号 结束
console.log(obj.uname);
console.log(obj[‘sex’]);
obj.sayHi();
因为一次创建一个对象,里面很多属性和方法是大量相同的,我们只能复制
因此我们可以利用函数的方法 重复这些相同的代码 我们就把这个函数称为构造函数
构造函数:就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
构造函数语法格式:
function 构造函数名(){
this.属性=值;
this.方法=function(){}}
new 构造函数名();
function() Star(uname,age,sex){
this.name = uname;
this.age = age;
this.sex = sex;
this.sing =function(song){console.log(song);}
}
var ldh = new Star(‘刘德华’,‘18’,‘男’);//调用函数返回的是一个对象
console.log(ldh);
ldh.sing(‘冰雨’);
//1.构造函数名字首字母要大写
//2.构造函数不需要return,就可以返回结果
//3.我们调用构造函数必须使用new
//4.我们只有new Star() 调用函数就创建一个对象 ldh{}
//5.我们的属性和方法前面必须添加this
new在执行时会做四件事情:
1.在内存中创建一个新的对空对象
2.让this指向这个新的对象
3.执行构造函数里面的代码,给这个新对象添加属性和方法
4.返回这个新对象(所以构造函数里面不需要return)
var obj = {
name:‘pink’,
age:18,
sex:‘男’,
fn:function(){}
}
for(var k in obj){
console.log(k);//k 变量 输出 得到的是 属性名
console.log(obj[k]);//obj[k]得到的是 属性值
}
//我们使用for in 里面的变量 我们喜欢写 k 或者key
JavaScript中的对象分为3种:自定义对象,内置对象,浏览器对象。
前面两种对象是JS基础内容,属于ECMAScript;第三个属于js独有的。
内置对象就是指js语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或者是最基本而必要的功能(属性和方法)
常见的内置对象:Math,Date,Array,String等
查文档:MDN
console.log(Math.max(-1,-10));//返回-1 返回最大值
Math.abs(-1);//绝对值 输出为1
Math.abs(’-1’);//输出还是为-1,隐式转换 会把字符串-1转换为数字型
Math.abs(‘嘿嘿’);//NaN
Math.floor(1.1);// 1 向下取整
Math.floor(1.9);// 1
Math.ceil(1.1);// 2 向上取整
Math.ceil(1.9);// 2
Math.round(1.1);// 1四舍五入 ,但.5特殊 往大的取
Math.round(1.5);// 2
Math.round(-1.5);// -1
Math.random();
//random() 返回一个随机小数 0 =< x <1
这个方法里面不跟参数
console.log(Math.random());
Math.floor(Math.random()*(max - min + 1)) + min;//我们想要得到两个数之间的随机整数 并且 包含这两个整数
function getRandom(min,max){
return Math.floor(Math.random()*(max - min + 1)) + min;
}
console.log(getRandom(1,10));
var arr = [ ‘张三’,‘张思’,‘张思德’,‘李四’,‘李就’,‘思德’];//随机点名
console.log(arr[getRandom(0,arr.length - 1)]);
var date = new Date();
console.log(date); //使用Date 如果没有参数 返回当前系统的时间
var date1 = new Date(2019,10,1);
console.log(date1);//返回的月份是11月 不是10月
var date2 = new Date(‘2019-10-1 8:8:8’);//也可以写成2019/10/1
console.log(date2);
var date = new Date();
console.log(date.getFullYear());//返回当前日期的年
console.log(date.getMonth() + 1);//月份 返回的月份少1个月
console.log(date.getDate());//返回的是 几号
console.log(date.getDay());//周一返回的是1 周六返回的是6 但是周日返回的是0
//我们写一个2019年5月1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = [‘星期日’,'星期一,‘星期二’,‘星期三’,‘星期四’,‘星期五’,‘星期六’];
var day = date.getDay();
console.log(‘今天是:’ + year + ‘年’ + month + ‘月’ + dates + '日 ’ + arr[day]);
var date = new Date();
console.log(date.getHours);//时
console.log(date.getMinutes);//时
console.log(date.getHours);//时
//要求封装一个函数返回当前的时分秒
function getTime(){
var h = new Date();
var h = time.getHours();
h = h < 10 ? ‘0’ + h : h;
var m = time.getMinutes();
m = m < 10 ? ‘0’ +m : m;
var s = time.getSeconds();
s = s < 10 ? ‘0’ + s : s;
return h + ‘:’ + m + ‘:’ + s;}
console.log(getTime());
Date对象是基于 1970年1月1日(世界标准时间)起的毫秒数。毫秒数更精确。毫秒数不会重复。
//1.通过 valueOf() getTime()
var date = new Date();
console.log(date.valueOf());
console.log(date.getTime());
//2.简单的写法(最常用的写法)
var date1 = +new Date();//+new Date() 返回的就是总的毫秒数
consol.log(date1);
//3.H5 新增的 获得总的毫秒数
console.log(Date.now());
1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时,但是不能拿着时分秒相减,比如05-25分,结果是负数。
2.用时间戳来做。用户输入的时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
3.把剩余时间的毫秒数转换为天,时,分,秒,(时间戳转化为时分秒)
转换公式:
// d = parseInt(总秒数/ 60 / 60/ 24);//计算天数
// h = parseInt(总秒数/ 60 / 60 % 24);//计算小时
// m = parseInt(总秒数/ 60 %60 );//计算分数
// s = parseInt(总秒数% 60);//计算当前秒数
function countDown(time) {
var nowTime =+new Date();//返回当前时间总的毫秒数
var inputTime = +new Date(time);//返回的是用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000;//times是剩余时间总的秒数
d = parseInt(times/ 60 / 60/ 24);
d = d < 10 ? ‘0’ + d : d;
h = parseInt(times/ 60 / 60 % 24);
h = h < 10 ? ‘0’ + h : h;
m = parseInt(times/ 60 %60 );
m = m < 10 ? ‘0’ + m : m;
s = parseInt(times% 60);
s = s < 10 ? ‘0’ + s : s;
return d + ‘天’ + h + ‘时’ + ‘分’ + s + ‘秒’;
}
console.log(countDown(‘2021-5-1 18:00:00’));
var date =new Date();
console.log(date);
创建数组的两种方式
1.利用字面量
var arr = [1,2,3];
console.log(arr[0]);
2.利用new Array()
//var arr1 = new Array();//创建了一个空的数组
//var arr1 =new Array(2);//这个2表示数组的长度为2 里面有两个空的数组元素
var arr1 = new Array(2,3);//等价于 [2,3] 这样写表示 里面有两个数组
console.log(arr1);
//(1)instanceof 运算符 它可以用来检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
(2)Array.isArray(参数);H5新增的方法 ie9 以上版本支持
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
//1.push() 在我们数组的末尾 添加一个或者多个数组元素
var arr = [1,2,3,4];
console.log(arr.push(4,‘5’));
console.log(arr);
//(1)push是可以给数组后面追加新的元素
//(2)push()参数直接写 数组元素就可以了
//(3)push完毕之后,返回的结果是 新数组的长度
//(4)原数组也会发生变化
//2.unshift 在我们数组的开头 添加 一个或者多个数组元素
arr.unshift(‘red’,‘purple’);
console.log(arr);
//(1)unshift是可以给数组前面追加新的元素
//(2)unshift()参数直接写 数组元素就可以了
//(3)unshift毕之后,返回的结果是 新数组的长度
//(4)原数组也会发生变化
//3.pop()它可以删除数组的最后一个元素
console.log(arr.pop());
console.log(arr);
//(1)pop是可以删除数组的最后一个元素 记住一次只能删除一个
//(2)pop()没有参数
//(3)pop完毕之后,返回的结果是 删除的那个元素
//(4)原数组也会发生变化
//4.shift()它可以删除数组的第一个元素
console.log(arr.unshift());
console.log(arr);
//(1)shift是可以删除数组的第一个元素 记住一次只能删除一个
//(2)shift()没有参数
//(3)pop完毕之后,返回的结果是 删除的那个元素
//(4)原数组也会发生变化
//1.翻转数组
var arr = [ ‘pink’, ‘red’, ‘blue’];
arr.reverse();
console.log();
//2.数组排序(冒泡排序)
var arr1 = [13, 4,77,1,7];
arr1.sort(function(a,b) {
//return a - b;升序的顺序排列
return b - a;//降序的顺序排列
})
console.log(arr1);
返回数组元素索引号方法 indexOf(数组元素) 作用就是返回该数组元素的索引号
它只返回第一个满足条件的索引号
如果该数组里面找不到元素,则返回-1
var arr = [‘red’,‘green’,‘blue’,‘pink,‘blue’],
console.log(arr.indexOf(‘blue’));//3
console.log(arr.indexOf(‘blue’,3));//3
console.log(arr.lastIndexOf(‘blue’));//5
function unique(arr){
var newArr = [];
for(var i = 0; i < arr.length; i++) {
if(newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}}
return newArr;
}
var demo = unique([‘blue’,‘green’,‘blue’,‘a’]);
console.log(demo);
//数组转换为字符串
//1.toString() 将我们的数组转换为字符串
var arr =[1,2,3];
console.log(arr.toString());//1,2,3
//2.join(分隔符)
var arr1 = [‘green’,‘blue’,‘pink’];
console.log(arr1.join());//green,blue,pink
console.log(arr1.join(’-’));//green-blue-pink
console.log(arr1.join(’&’));//green&blue&pink
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BDhibbMp-1641396761444)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025130507754.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96L2YWDz-1641396761448)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025155228307.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KB6DS6Fr-1641396761449)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025155328439.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odxHafuC-1641396761451)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025160507062.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CsVOPYPg-1641396761453)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025160553692.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3h0gf7jr-1641396761453)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025160337749.png)]
BOM是browser object model的缩写。是用来获取或设置浏览器的属性、行为,例如:新建窗口、获取屏幕分辨率、浏览器版本号等。 比如 alert();弹出一个窗口,这属于BOM
window.document window.frames window.history window.location
document.anchors document.forms
**DOM是Document object model 。是用来获取或设置**文档中标签的属性,例如获取或者设置input表单的value值。document.getElementById("").value; 这属于DOM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Kpb2l5c-1641396761456)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025161158890.png)]
BOM的内容不多,主要还是DOM。 由于DOM的操作对象是文档(Document),所以dom和浏览器没有直接关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-medDwn8p-1641396761457)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025162335925.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTtANiG3-1641396761458)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025163030712.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObB0GDUA-1641396761459)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025163105173.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaMiUjkw-1641396761460)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025163343055.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GojOsBrR-1641396761461)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025164018234.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XCUKIrG9-1641396761462)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025165457138.png)]
推荐使用innerHTML
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xvFwi5B9-1641396761463)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025170046568.png)]
操作元素之修改元素属性
可以修改src,href,title,alt属性哦
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6GMP8JYp-1641396761465)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201025170602265.png)]
修改表单属性
input里面的内容,不能通过innerHtml修改,必须要value
this.disabled = ture;//禁用某个表单元素 如button,this指向的是事件函数的调用者
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-maE26n4t-1641396761465)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201026162259142.png)]
操作元素
样式属性操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KMeMKVR9-1641396761471)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201026191435118.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M8RVFMqA-1641396761474)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201026191507513.png)]
操作元素总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Z6cLl6Z-1641396761476)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201031095635041.png)]ss
用得多的是e.pageX,e.pageY
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0KjUcdqr-1641396761477)(C:\Users\courage\AppData\Roaming\Typora\typora-user-images\image-20201031183834054.png)]
闭包(closure)是 JavasSript 的一大难点,也是它的特色。很多高级应用都要依靠闭包来实现。
要理解闭包,首先要理解 JavasSript 的特殊的变量作用域。
变量的作用域无非就两种:全局变量和局部变量。
JavasSript 语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。
注意点:在函数内部声明变量的时候,一定要使用 var 命令。如果不用的话,你实际上声明的是一个全局变量!
2、如何从外部读取函数内部的局部变量?
出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。
那就是在函数内部,再定义一个函数。
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
在上面的代码中,函数 f2 就被包括在函数 f1 内部,这时 f1 内部的所有局部变量,对 f2 都是可见的。但是反过来就不行,f2 内部的局部变量,对 f1 就是不可见的。
这就是 JavasSript 语言特有的"链式作用域"结构(chain scope),
子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。(作用域链的查找顺序是由里向外的,js执行顺序是从上而下的。函数声明比变量声明更优先)
既然 f2 可以读取 f1 中的局部变量,那么只要把 f2 作为返回值,我们不就可以在 f1 外部读取它的内部变量了吗!
上面代码中的 f2 函数,就是闭包。
各种专业文献的闭包定义都非常抽象,我的理解是: 闭包就是能够读取其他函数内部变量的函数。
由于在 JavasSript 中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成"定义在一个函数内部的函数"。
所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在 f1 调用后被自动清除。
为什么会这样呢?原因就在于 f1 是 f2 的父函数,而 f2 被赋给了一个全局变量,这导致 f2 始终在内存中,而 f2 的存在依赖于 f1,因此 f1 也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是 “nAdd=function(){n+=1}” 这一行,首先在 nAdd 前面没有使用 var 关键字,因此 nAdd 是一个全局变量,而不是局部变量。其次,nAdd 的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以 nAdd 相当于是一个 setter,可以在函数外部对函数内部的局部变量进行操作。
回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后**把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。**函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。
箭头函数前后必须有空格
为什么叫Arrow Function?因为它的定义用的就是一个箭头:
x => x * x
上面的箭头函数相当于:
function (x) {
return x * x;
}
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ ... }
和return
都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }
和return
:
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
如果参数不是一个,就需要用括号()
括起来:
// 两个参数:
(x, y) => x * x + y * y
如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:
// SyntaxError:
x => { foo: x }
因为和函数体的{ ... }
有语法冲突,所以要改为:
// ok:
x => ({ foo: x })
现在,箭头函数完全修复了this
的指向,this
总是指向词法作用域,也就是外层调用者obj
和普通函数相比,箭头函数主要就是以下两个方面的特点
什么叫不绑定this,我个人的理解为箭头函数的this其实就是在定义的时候就确定好的,以后不管怎么调用这个箭头函数,箭头函数的this始终为定义时的this
js立即执行函数可以让你的函数在创建后立即执行,js立即执行函数模式是一种语法,可以让你的函数在定义后立即被执行,这种模式本质上就是函数表达式(命名的或者匿名的),在创建后立即执行。
一、JS立即执行函数的写法
方式1、最前最后加括号
(function(){alert(1);}());
方式2、function外面加括号
(function(){alert(1);})();
方式3、function前面加运算符,常见的是!与void
!function(){alert(1);}();
void function(){alert(2);}();
二、立即执行函数的参数
可以给立即执行函数传递参数,例如
(function(who, when) {
console.log("I met " + who + " on " + when);
} ("Joe Black", new Date()));
记住:
1、立即函数内部是可以访问外部变量的,所以很多情况下,我们并不需要传参数。
如:jQuery的window实参,如果不传入。内部也是可以直接使用的。
2、通常你不应该给立即执行函数传递太多的函数,因为它很快会成为一个负担——为了理解代码是如何工作的,你不得不经常上下滚动源代码。
三、立即执行函数的返回值
像其它任何函数一样,一个立即执行函数也能返回值并且可以复制给其它变量,例如
var result = (function () {
return 2 + 2;
}());
var result = (function () {
return 2 + 2;
})();
四、立即执行函数的好处
1、立即执行函数模式被广泛使用,它可以帮你封装大量的工作而不会在背后遗留任何全局变量。
2、定义的所有变量都会成为立即执行函数的局部变量,所以你不用担心这些临时变量会污染全局空间。
3、这种模式经常被使用在书签工具(bookmarklets)中,因为书签工具在任何页面上运行并且保持全局命名空间干净是非常必要的;
4、这种模式也可以让你将独立的功能封装在自包含模块中。
5、可以将这些代码封装进一个立即执行函数中,并且确保页面没有它的情况下也能正常工作。
6、可以添加更多的加强模块,移除它们,单独测试它们,允许用户去禁用它们等等。
https://www.cnblogs.com/loveyaxin/p/11151586.html
https://www.jianshu.com/p/f30fa27999e3
一、prototype
在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XtkEhAg1-1641396761481)(img/850375-20190708151024134-512558007.png)]
二、proto
这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ezjC72L0-1641396761482)(img/850375-20190708151322530-1608157973.png)]
三、constructor
每个原型都有一个constructor属性,指向该关联的构造函数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbYBPh6z-1641396761482)(img/850375-20190708151615691-1017611190.png)]
四、原型链
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5sTMs7K-1641396761483)(img/850375-20190708153139577-2105652554.png)]
常用元字符
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
常用限定符
代码/语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
常用反义词
代码/语法 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
常用模式修正符
代码/语法 | 说明 |
---|---|
i | 表示在进行匹配的时候不区分大小写 |
m | 多行识别.即将字符串视为多行,不管是那行都能匹配 |
s | 将字符串视为单行,转义回车换行符作为普通字符 |
g | 表示全局匹配 |
x | 将模式中的空白忽略 |
A | 强制从目标字符串开头匹配 |
D | 强制尾部无任何内容.若使用$限制结尾字符,则不允许结尾有换行 |
U | 禁止贪婪匹配,只匹配最近的一个字符串(不重复匹配) |
e | 配合PHP函数preg_replace()使用,可以把匹配来的字符串当作正则表达式执行 |
1. 基本组成
Brocket:括号
Caret:插入符号
Dollars:美元符号
2. 几种括号
[ 方括号:内包括需要匹配的字符;
{ 花括号:指定匹配字符的数量;
( 圆括号:用来分组。
3.开始结束符号
^:表示开始;$表示结束
4.一些快捷命令
可以用\d代替[0-9]:表示匹配0至9的数字
可以用\w代替[a-z][0-9][_]
\s代表任意空白符
\b单词的开始或结束
*:0次或多次发生
+:至少一次发生
?:0或1次发生
Promise
是一个对象,它代表了一个异步操作的最终完成或者失败。放在任务队列中。
有三种状态:
菜鸟教程:https://www.runoob.com/w3cnote/javascript-promise-object.html
https://www.jianshu.com/p/d8a901dd72ac
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,**无法取消 Promise,**一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
promise的状态一旦改变之后不可变
promise如何解决地狱回调
then里面可以return Promise,来防止地狱回调,不用then一直嵌套下去
.catch(()=>{console.log(“失败”);})//用catch方法来接受失败
.finally(()=>{console.log(“无论成功或者失败,都要执行”);})//无论成功或者失败,都要执行
.then()
.all([]).then(res => {}).catch(err => {})
只有当该数组中的所有Promise完成后才会由pendding
状态变为resolve
执行then里面的回调函数,若数组中有任意一个promise被拒绝则会执行失败回调,catch方法会捕获到首个被执行的 reject函数。
.any([]).then(res => {}).catch(err => {});
当传入的promise数组中有任意一个完成时就会终止,会忽略到所有被拒绝掉的promise,直到第一个promise完成。若传入所有的promise被拒绝则会执行拒绝回调。
.race([]).then(res => {}).catch(err => {});
当promise数组中任意一个promise被拒绝或者成功,则会采用第一个promise作为他的返回值。若为成功的执行then,若失败则执行catch。
resolve()调用的是then里面的内容
async函数是使用async
关键字声明的函数。 async函数是AsyncFunction
构造函数的实例, 并且其中允许使用await
关键字。async
和await
关键字让我们可以用一种更简洁的方式写出基于Promise
的异步行为,而无需刻意地链式调用promise
。
生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议。
阮一峰:《ECMAScript 6入门》
https://es6.ruanyifeng.com/#docs/symbol
export default 和 export 区别
https://www.jianshu.com/p/edaf43e9384f
1.export与export default均可用于导出常量、函数、文件、模块等
2.你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
3.在一个文件或模块中,export、import可以有多个,export default仅有一个
4.通过export方式导出,在导入时要加{ },export default则不需要
1.export
//a.js
export const str = "blablabla~";
export function log(sth) {
return sth;
}
对应的导入方式:
//b.js
import { str, log } from 'a'; //也可以分开写两次,导入的时候带花括号
2.export default
//a.js
const str = "blablabla~";
export default str;
对应的导入方式:
//b.js
import str from 'a'; //导入的时候没有花括号
使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名
//a.js
let sex = "boy";
export default sex(sex不能加大括号)
//原本直接export sex外部是无法识别的,加上default就可以了.但是一个文件内最多只能有一个export default。
其实此处相当于为sex变量值"boy"起了一个系统默认的变量名default,自然default只能有一个值,所以一个文件内不能有多个export default。
// b.js
本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含
import any from "./a.js"
import any12 from "./a.js"
console.log(any,any12) // boy,boy
http://www.ruanyifeng.com/blog/2015/04/tail-call.html
尾调用是函数式编程的一个重要概念,是指某个函数的最后一步是调用另一个函数。
ES6的尾调用优化只在严格模式下开启,正常模式是无效的。
1.JSONP方式解决跨域问题(实际中不推荐使用)
jsonp解决跨域问题是一个比较古老的方案,这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)
实现原理
JSONP之所以能够用来解决跨域方案,主要是因为Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如**<\script>、<\img>、<\iframe>)。**
如果想通过纯web端跨域访问数据,可以在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
2.CORS请求
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
基本上目前所有的浏览器都实现了CORS标准,其实目前几乎所有的浏览器ajax请求都是基于CORS机制的,只不过可能平时前端开发人员并不关心而已(所以说其实现在CORS解决方案主要是考虑后台该如何实现的问题)。
关于CORS,强烈推荐阅读
跨域资源共享 CORS 详解(阮一峰)
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET
请求,**CORS支持所有类型的HTTP请求。**JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
3.Nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发。
1、 非vue框0架的跨域(2次跨域)
利用node + express + http-proxy-middleware搭建一个proxy服务器。
1.)前端代码示例:
var xhr = new XMLHttpRequest();
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
// 访问http-proxy-middleware代理服务器
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();
2.)中间件服务器:
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/', proxy({
// 代理跨域目标接口
target: 'http://www.domain2.com:8080',
changeOrigin: true,
// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
res.header('Access-Control-Allow-Credentials', 'true');
},
// 修改响应信息中的cookie域名
cookieDomainRewrite: 'www.domain1.com' // 可以为false,表示不修改
}));
app.listen(3000);
console.log('Proxy server is listen at port 3000...');
3.)Nodejs后台同(六:nginx)
2、 vue框架的跨域(1次跨域)
利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers跨域信息了。
webpack.config.js部分配置:
module.exports = {
entry: {},
module: {},
...
devServer: {
historyApiFallback: true,
proxy: [{
context: '/login',
target: 'http://www.domain2.com:8080', // 代理跨域目标接口
changeOrigin: true,
cookieDomainRewrite: 'www.domain1.com' // 可以为false,表示不修改
}],
noInfo: true
}
}
4.nginx代理跨域
1、 nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
2、 nginx反向代理接口跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
参考:https://www.cnblogs.com/roam/p/7520433.html
5.WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。