JavaScript基础学习
Posted 自由早晚乱余生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript基础学习相关的知识,希望对你有一定的参考价值。
前端基础学习-javascript
JavaScript 简介
JS的简介
在上个世纪的1995年,当时的网景公司正凭借其 Navigator 浏览器成为 Web时代开启时最著名的第一代互联网公司。由于网景公司希望能在 静态html页面上 添加一些动态效果,于是叫 Brendan Eich 这哥们在两周之内设计出了JavaScript语言。
为什么起名叫 JavaScript?原因是当时Java语言非常红火,所以网景公司希望借Java的名气来推广,但事实上JavaScript除了语法上有点像 Java,其他部分基本上没啥关系。
在JavaScript中,是以对象为王的,在JavaScript中几乎所有的东西都是对象或者以对象的形式展现出来的。所以在学习之前,先理解一下什么叫面对对象编程。
面向对象编程介绍
面向对象是一种编程思想,其实跟Java、C++是一样的,JavaScript也是一门面向对象的编程语言。说到面向对象就不得不提出来面向过程的编程思想,可以和面向对象做一个对比。
面向过程就是分析出来解决问题所需要的步骤,然后使用方法函数将这些步骤一步一步的实现,使用的时候再一个一个的一次调用就可以了,比如C语言,性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。没有面向对象易维护、易复用、易扩展。
面向对象是把事务分解成一个个对象,然后由对象之间分工与合作,面向对象是以独享功能来划分问题的,而不是步骤。在面向对象程序开发思想中,每一个独享都是功能中心,具有明确的分工,面向对象编程具有灵活性、可复用性、易维护性、和容易开发等优点,适合多人合作的大型软件项目。
面对对象编程的特性:
- 封装性
把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
- 继承性
指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
- 多态性
指一个类实例的相同方法在不同情形有不同表现形式。
JS 的组成
js = ECMAScript + DOM + BOM + 高级
ECMAScript(前身为欧洲计算机制造商协会):JavaScript的语法规范
DOM(Document Object Model 的文档对象模型简称):JavaScript操作网页上元素的API
BOM(Browser Object Model 的浏览器对象模型简称):JavaScript操作浏览器部分功能的API
JS的作用与书写位置
JavaScript的最基本功能是控制网页中的元素
当然,第一点应该是把JavaScript脚本写在脚本对里。并且JavaScript语言是区分大小写的。所以一般情况下,JavaScript的书写位置有内嵌式和外链式两种
内嵌式:
一般放在body里面的最后,有时放在head标签中(需要写页面加载函数)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div>
<div>
<span>hello</span>
</div>
<h2>JS 的书写位置</h2>
</div>
<script type="text/javaScript">
var str = "hello, javaScript"
alert(str)
</script>
<script src="../index/index.js" type="text/javascript"></script>
</body>
</html>
? 因为代码的顺序都是从上往下加载,在 body 中的元素,如果在js中获取body中元素的时候,会报错找不到。
外链式:
src=”外部js文件路径”
变量和流程控制
变量的声明和初始化
var number // 变量的声明,没有赋值 undefined
var name = "Hello"; // 变量的初始化
var NAME= "hello"
var 你好 = "你好" // 不推荐
命名规则(驼峰命名)
和Java一样,JavaScript采用的是驼峰式命名,
- 变量命名必须以字母或是下标符号 "_" 或者 "$" 为开头。
- 变量名长度不能超过 255 个字符。
- 变量名中不允许使用空格,首个字不能为数字。
- 不用使用脚本语言中保留的关键字及保留符号作为变量名。
- 变量名区分大小写。
- 汉语可以作为变量名。但是不建议使用!
数据类型
基本数据类型
- String 字符串
- Number 数字
- Boolean :
true / false
- undefined 未定义
- null 空
- symbol (ES6 引入了一种新的原始数据类型)
复杂数据类型
- Object 对象
- Function 函数
- Array 数组
- Date 日期
- Error 错误
类型判断 instanceof / typeof
var arr = []
console.log(typeof arr) //object
console.log(arr instanceof Array) // true
类型转换
var weightIncrease ="2.5斤"
parseInt(weightIncrease) //2
parseFloat(weightIncrease) //2.5
文本字符串操作
var words="十三是个大胖子"
words.length //7
words.charAt(0) //十
words.charAt(words.length-1) //胖
words.indexOf("胖") //5
words.substring(0,2) //十三
words.replace(‘胖子‘,‘瘦子‘) //"十三是个大瘦子"
var words="十三,是个大胖子"
words.split(‘,‘) //["十三,是个大胖子"]
文本字符串的操作跟其他语言的操作时差不多的,具体的用到时候可以再查。
数组操作
var arr=[];
typeof(arr) //"object"
arr=[‘十三‘,‘是个‘,‘大胖子‘]; //(3)["十三", "是个", "大胖子"]
arr.length; //3
arr[0]; //"十三"
arr[3] =‘?‘; //"?" 数组变成 (4)["十三", "是个", "大胖子", "?"]
arr.push(‘@‘); //5 数组变成 (5)["十三", "是个", "大胖子", "?","@"]
arr.pop(); //@ 删除掉数组中的最后一个元素,并返回这个元素 数组变成 (4)["十三", "是个", "大胖子", "?"]
arr.shift(); //十三 删除掉数组中的第一个元素,并返回这个元素 数组变成 (3)[ "是个", "大胖子", "?"]
delete arr[2]; //true 删除数组指定位置的元素,但不改变数组长度返回true 数组变成: ["是个", "大胖子", empty]
arr.splice(2) //[empty] 删除指定位置元素,并返回删除的元素,改变数组长度 数组变成["是个", "大胖子"]
var arr1=["32","1","0"]
var arr2=arr1.concat(arr); //合并数组 (5)?["32", "1", "0", "是个", "大胖子"]
null和undefined的理解和应用
undefined是JavaScript中的一大特点,是JAVASCRIPT独有的数据和数据类型(这种数据类型只有这个一值,就是undefined,它的类型也是undefied),既然它是JAVASCRIPT独有的一种数据类型,所以需要特殊关注一下
在JAVASCRIPT里,null和undefined都表示不存在的数据,并且undefined也是从null中继承而来,那null是什么?undefined又是什么?它们两个又有什么共性和区别呢,请看下面的描述:
- null和undefined都是表示没有的、不存在的值。它们两个在进行逻辑转换时都是false,这两个值进行比较是true。
- null表示空引用,它是object类型。undefined表示未定义, 它是undefined类型。
- 如果一个变量的值是null,那么必须主动的给它赋值null。
- 一个变量未定义,或一个变量定义了未赋值,则是undefined。需要注意的是:一个变量如果没有定义,是不能直接在程序里使用的(就不是不能直接读取这个变量,但可以赋值)。比如说:本来没有定义一个叫a的变量
但我直接去alert(a);//在浏览器里这样是个语法错误,但是可用typeof去运算
但如果a定义了,未赋值,可以读,它的值就是undefined,如果用typeof去运算,那它的类型也是undefined。- 对说属性来说:如果原来没有这个属性,根本就不存在这个属性,那么它的值就是undefined。对象的属性不需要定义,如果不存在也可以直接去读,不会报错,而会给出一个undefined的值来。
- 如果这个对象以后要用,但是现在还没有值,一般情况下,会给它一个null值。
- 在函数(方法)里,如果必须返回值,但是值又计算不出来,那就返回一个null(这是规范,而不是语法规定,JAVASCRIPT里遵循这一规范)。比如网页中没有一个id是div2的元素,则下面的这句脚本则返回null
document.getElementById(‘div2‘);//返回null。
但是,没有返回值的函数,它的返回值都是undefined。
在JavaScript编程实践中,如果一个变量以后要用到,现在就要定义,那我们就主动给它一个null值,虽然只定义不赋值也没有什么错误。比如以后在动画中要定义一个定时器变量,就是:var timer=null;就表示这个timer是提前定义的,以后要用,当然你也可以不给它这个null,就是直接写一个var timer;这样也没问题,不会有什么语法错误,它的值自动就是undefined,也表示一个不存在的值的。主动把null赋给timer,就是为了强调这个变量是提前预留出来的。
判断JavaScript中一些对象的属性时,也遵循这个原则,如果一个对象的属性根本就没定义过,则它是undefined;如果是null,则表示这是个本来就有的属性,只是没有值。比如说一个网页元素的parentNode这个属性,表示是这个网页元素的父节点,这是个系统规定的(法定的)的法性,一般情况这个属性的值是一个网页元素,但它的值也有为null的时候,比如:document.parentNode,这个就是null,因为它有parentNode这个属性,只不过它是顶级元素,不存父节点而已。但是它不是undefined,如果是undefined表示这个属性根本就没有定义(声明)过。
这个在调试JavaScript时非常有用,如果你调试某一个属性的值是undefined,那说明你可能把这个属性写错了,除非你在直接读取一个你从来没有操作过的自定义属性。
运算符
比较运算符
比如x=5
运算符 | 描述 | 比较 | 返回 |
---|---|---|---|
== | 等于 | x == 8 | false |
x == 5 | true | ||
x == "5" | true | ||
=== | 值相等并且类型相等 | x === 5 | true |
x === "5" | false | ||
!= | 不相等 | x != 8 | true |
!== | 值不相等或类型不相等 | x !== 5 | false |
x !== "5" | true | ||
x !== 8 | true | ||
> | 大于 | x > 8 | false |
< | 小于 | x < 8 | true |
>= | 大于或等于 | x >= 8 | false |
<= | 小于或等于 | x <= 8 | true |
逻辑运算符
给定 x = 6 且 y = 3,下表解释了逻辑运算符:
运算符 | 描述 | 例子 |
---|---|---|
&& | 与 | (x < 10 && y > 1) 为 true |
|| | 或 | (x == 5 || y == 5) 为 false |
! | 非 | !(x == y) 为 true |
条件(三元)运算符
JavaScript 也包含了可基于某些条件向变量赋值的条件运算符。
语法
variablename = (condition) ? value1:value2
实例
var voteable = (age < 18) ? "太年轻":"足够成熟";
js中不同类型作比较的规律(布尔运算)
类型 | 类型 | 规律 | 其它说明 |
---|---|---|---|
对象 | 对象 | 比较是不是同一个内存地址 | |
对象 | 字符串 | 对象先转化为字符串,然后做比较 | |
对象 | 布尔类型 | 两边都要先转为数字(false是0,true是1)。是对象类型先隐式调用toString方法,然后再Number() | alert([]false); alert([]0) alert([1]1); alert([1]true) alert([2]==true) |
对象 | 数字 | 对象要转为数字,再进行比较(对象先隐式调用toString方法转化为字符串,然后再把这个字符串轮化为数字,相当于把这个字符串放到Number这个方法中) | |
数字 | 布尔 | 是进行的数字的比较 | |
数字 | 字符串 | 把字符串转化为数,再比较 | |
布尔 | 把两边都要转化为数字再进行比较 | ||
null | undefined | true | |
null,undefined | 和其它类型 | null和undefined和其它类型比较都是false(这两个对象没toString方法) | alert(nullfalse) alert(null0) alert(null=="");; |
流程控制
流程控制和java中是差不多的
if...else...
var weather=‘sunny‘,tempperature=26 ;
if((weather === ‘sunny‘) && (tempperature <= 26) ){
alter(‘happy‘);
}else{
alter(‘sad‘);
}
- while (true) {}
var i=0;
while(i<10){
i++;
if(i%2 === 0){
continue;
}
console.log(i);
}
for(var a=0;a<10;a++){}
for (var i=1;i < 10;i++) {
if (i % 2 === 0) {
continue;
}
console.log(i);
}
switch
//注意: switch 底层用的是 === 比较
switch ("1"){
case 1:
alert(1);
break;
case 1:
alert(1);
break;
case 3:
alert(3);
break;
default :
alert("都不是!");
break;
}
注意:如果 switch 的判断条件为 false 的话,case的所有语句都不执行,只执行default的语句
js代码的注意问题:
- 在一对script的标签中有错误的js代码,那么该错误的代码后面的js代码不会执行。
- 如果第一对的script标签中有错误,不会影响后面的script标签中的js代码执行。
- script标签里面可以写的内容:
type="text/javascript"
标准写法,或者language="JavaScript"
,都是可以省略的,原因是在html开头写了遵循h5标准。 - script标签可以出现多对。
- 如果使用引入外部js文件的方式,那么不要在script标签里面写任何js代码,如果想写,就新开一对script标签。
异常捕获
try...catch...finally
在程序中都会有对于异常的处理,这里看一下JavaScript对于异常的处理和java中的异常处理是一样的,都是用try,catch去捕获处理的。
try{
//可能会发生异常的代码
}catch(err){
//错误的处理
}
写个demo
<script>
function demo(){
try{
alert(str);
}catch(err){
alert(err);
}
}
demo(); //页面弹出:ReferenceError: str is not defined
</script>
Throw
可以通过throw语句创建一个自定义错误,大致用法和java中一样,但是js中不分那么多异常类,都是弱类型,直接抛出字符串就可以,下面看一个demo
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" id="txt" >
<input type="button" id="btn" onclick="demo()" value="确定">
<script>
function demo(){
var str=document.getElementById("txt").value;
try{
if(str == ‘‘){
throw "未输入用户名,请输入"; //当用户输入为空,则会自动抛出异常,和java中一样
}else{
alert(str);
}
}catch(err){
alert(err);
}
}
</script>
</body>
</html>
其实还有一种onerror() 语法可以用来捕获网页中的错误,但是这是一种老式的标准,除了IE之外主流的浏览器不太支持。所以不多赘述。
函数和变量
函数
函是fnuction一词翻译过来的,也叫方法,其实叫“功能”我认为更妥当,就是对一个功能的描述或定义,在JavaScript中,function关键定义了一个功能(或叫函数、方法、行为)。
函数本来就是对象类型的数据,但由于在JavaScript语言中有着非常突出的地位,所以把函数也单独成一种数据类型了,就是function类型。就是说你首先要知道函数本身是对象类型的。
定义方法
定义方法有两种方式 声明式 和函数表达式
声明式
函数就是包裹在花括号中的若干代码块,前面使用了关键词 function:
function functionName (parmeter1,parmeter2...) {
这里是要执行的代码
}
//执行的时候要在方法名后面加一对括号,并且还要有执行的主体
functionName(parmeter1,parmeter2...);
函数表达式
var functionName= function (parmeter1,parmeter2...){
这里是要执行的代码
} //这样把方法的定义赋给一个变量,叫函数表达式。
//执行方式和声明式是一样的
functionName(parmeter1,parmeter2...);
这个表达式其实是分三步运行的
第一步:先定义一个变量functionName,这一步是预解释的;
第二步:定义一个方法(函数);
第三步:把这个方法赋的引用地址赋给functionName这个变量。
匿名函数
定义一个方法但不起名字,那这个就叫做匿名方法。
function(){alert(“我是个匿名方法!”)}
单纯定义是没有意思,浏览器也会报错,由于匿名方法是没有方法名字所以所以单纯的定义后,方法是无法调用的,匿名函数也是可以执行的,并且还可以传参数
例如
<script>
;(function(){
alert(‘这是自动执行的匿名方法!‘);
})();
;(function (a,b) {
var c=a*b;
alert(c);
})(45,34); //1530
//注意,定义自动执行的匿名函数需要前面加分号;要不然后面的括号会和前面的表达式粘在一起,浏览器无法识别
//匿名方法在定义的时候也要用小括号把方法定义括起来。如果不加括号,后面表示运行的括号会与括号前的花括号结合,浏览器无法识别会出现语法错误
</script>
返回值
不管是声明式还是表达式的方式定义的函数,都可以使用return来表达函数的返回值
return的意思是中断当前这个方法的运行并且把它后面的数据返回,你需要把握好以下四点:
- return必须用在方法里,否则是语法错误。
- 在方法里只要是遇上return这个关键字,则当前的这个方法无条件的中止运行。
- return后面可以跟一个数据,表示中止当前的运行并且把后面的数据返回,即程序运行完成后,会留下这个数据。
- 如果return后没有数据(或根本就没有return),则这个方法会留下一个undefined
arguments
方法里还有两个内置的对象,就是说你定义一个方法,就会天生出现两个对象,一个叫arguments,一个叫this。先说arguments,它是一个类似于数组的对象,就是说它像数组一样保存着传入方法的所有参数。如下例:
**示例1
**
<script type="text/JavaScript">
function show(a, b){
alert(‘参数1‘+arguments[0]+‘参数2‘+arguments[1]+‘,参数长度:‘+arguments.length);
}
show(3, 6);//输出:第一个参数是3第二个参数是6,参数的长度是:2
</script>
arguments[0]和arguments[1]分别表示第一个参数a和第二个参数b,就是它把传进来的参数,按顺序依次保存在自己的[0]和[1]的位置上了。并且arguments本身还有一个属性length,表示传进来的参数的个数。
当然,也可以不写这两个形参a和b,看下面的代码就没有写形参
示例2
写一个方法,求任意个数字之和,实现如下:
<script type="text/ecmascript">
function add(){//不指定形式参数
var a=arguments;//参数集合,它也一个叫length属性。
var count=null;//为什么把null值赋给count呢,而不是0呢?
for(var i=0;i<a.length;i++){//做一个循环,动态取得传进来的参数。
count+=a[i];
}
return count;
}
alert(add()) //不传参数,输出null
alert(add(1,21,9)) //输出31
alert(add(-1,0,1,9,786))//这样就可以任意输入参数了,更灵活。输入的这些参数,都保存在add这个方法的arguments这个对象里
</script>
this关键字
每一个行为发生的时候,肯定会有一个发生这个行为的主体,在中文里有第一人称“我”,这个我在吃饭这个行为,就表示吃饭的那个人是我。张三吃饭,则张三吃饭行为中的那个我,就是张三,李四吃饭,则这个吃饭行为里的我就是李四。
在编程语言里,同样也有“我”的概念,那就是this关键字。每一个定义的方法里,都会有一个this关键字,这个this关键不是由在那儿定义的来决定的,而是由谁来执行的决定的。这是判断this关键表示什么的重要原则。比如:
张三.吃饭();//这个吃饭里的this就是张三这个对象
也就是判断点(.)前面的对象是谁,那这个this就是谁。
但有的方法是直接执行的,前面没有点,就更没有执行的对象了,那this关键是谁呢?像alert方法,直接执行的,那alert方法里的this是谁呢?凡是可以象alert这样直接运行的方法,都是全局方法(全局方法叫函数),全局方法的执行,都相当于前面省略掉了window.,也就是说alert()相当于window.alert(),那这样直接运行的方法里的this关键字,肯定就是window了。
方法里的this表示的是那个对象,是由谁来执行决定的。和在那儿定义的没有关系
变量
作用域
和java中一样,函数以外声明的变量是全局变量,在函数外部声明的变量是局部变量,局部变量只能是在当前函数中去访问到,也不会和函数外边同名的变量冲突,在函数外部是无法访问的,全局变量是函数内外都可以访问的,所以说,局部变量就是函数的隐私。
每一个方法在运行的时候,都会开辟一个独立的内存空间,这个方法所需要的资源开销,比如说定义的变量等,都在这个独立的内存空间内,这个内存空间就叫做方法的作用域。JavaScript里的不同代码运行,是按作用域划分的。每一个方法的一次运行,就形成一个作用域(当然,多次运行就形成多个作用域,也就是会占用多个内存空间)。数据本身当然也是要当用内存空间的,一个字符串,一个数字的使用都会占用内存空间,当然一个对象类型的数据也会占一个空间,当然一个方法的定义也要占一定的内存空间了,但你一定要理解,方法定义占的空间,和方法运行占用的空间是两码事。方法的定义是固定的状态,定义了,就会一直在那儿。但方法的运行占用的内存是动态的:开始运行就占用一块内存,然后在这个内存里创建属于这个方法自己的变量和数据,当方法结束时,把这块内存释放掉(如果方法里的数据没有被别的地方占用)。方法的运行是动态的作用域。
在JavaScript中可以把所以的对象和方法的运行都看成作用域,每一个对象又存在于其它的作用域中,(生存链和作用域链)
JavaScript中也差不多,浏览器是网页中所有代码活动的最大空间,在JavaScript中用window来表示浏览器,它就是顶级作用域。凡是在之间直接定义的变量,都是这个顶级作用域 的变量,可以叫全局变量。定义在方法里的变量,也属于这个方法运行的时候的那个作用域(再啰嗦一次:方法运行时形成的作用域和这个方法本身、或者说跟这个方法名没有关联),可以称做私有变量。
在顶级作用域中不能访问下一级作用域里的变量,但下一级作用域中可以访问上一级作用域中的变量。
示例: 如果知道直角三角形的两个直角边的长,求斜边的长度。根据勾股定理,可以实现如下方法
function bevelEdge(a,b){
var c=Math.sqrt(a*a+b*b);
//Math.sqrt是数学方法,开平方的作用
return c;
}
下来看执行结果:
var c= bevelEdge(3,4); //5
运行过程是这样的:
- 把3赋给bevelEdge这个方法的a,把4赋给b。这个3和4叫实参。
- 然后在这个方法里做运算,把运算结果赋给c。
- 然后把c里的值返回(注意是把c里的值返回,而不是把这个符号返回)
- 然后再把返回的这个结果赋给c这个变量。
把这个方法的返回值赋给了c。虽然在方法里也有一个变量叫c,这儿的变量同样也叫c,但这两个同名变量之间没有什么关系,也不会相互影响。bevelEdge方法里的变量c,只能在这个方法运行的时候(注意是运行的时候,如果这个方法不运行,不会出现这个c)出现,并且是只在这个bevelEdge方法的内部。
事件
JavaScript语言里大多的方法,是由事件来触发执行的,即事件驱动型。编程语言里的事件,就是诸如:鼠标单击(click)、鼠标双击(dblclick)、鼠标悬停(mouseover)、鼠标移动(mousemove)、鼠标离开(mouseout),还有很多键盘的事件,象什么键按下键抬起之类的等等,现在的移动端媒体上的事件就更多了。
那事件驱动就是对象上的某个事件被触发时,执行某个方法的意思。
如果想让事件触发的时候执行某个方法,那就要先把一个方法注册到这个事件上来,以备事件触发的时候执行相对应的方法。即先注册(也叫事件绑定方法),当事件触发的时候执行注册的方法。注意:注册的时候,也就是事件绑定的时候,不能执行这个方法,而是把这个方法的引用赋给这个属性,当事件触发的时候,这个方法自动执行。
<button id="button1">测试1</button>
<script>
var ele=document.getElementById(‘button1‘);
function fn (){
alert("hello");
}
ele.onclick=fn;
</script>
绑定到某个元素的事件上的方法在运行的时候,this关键表示的是当前这个网页元素。就像上面的那个fn方法,当它运行的时候,方法里的this表示的是ele这个元素。
总结一下事件
把一个方法绑定到某个事件上,相当于日常生活中的“做计划”,是让这个事件指向这个方法的定义,以备以后执行,这会儿不执行,所以不要加括号。
事件属性相当于一个会自动执行的方法,前提是触发这个事件的时候。
谨记:如果把上面的23行的事件绑定写成这样是错误的ele.onclick=fn();因为这样表示把fn方法运行后的返回值赋给了onclick事件,fn方法没有返回值,那这就是个错误的操作了。
下面是js中常见的事件
属性 | 当以下情况发生时,出现此事件 |
---|---|
onabort | 图像加载被中断 |
onblur | 元素失去焦点 |
onchange | 用户改变域的内容 |
onclick | 鼠标点击某个对象 |
ondblclick | 鼠标双击某个对象 |
onerror | 当加载文档或图像时发生某个错误 |
onfocus | 元素获得焦点 |
onkeydown | 某个键盘的键被按下 |
onkeypress | 某个键盘的键被按下或按住 |
onkeyup | 某个键盘的键被松开 |
onload | 某个页面或图像被完成加载 |
onmousedown | 某个鼠标按键被按下 |
onmousemove | 鼠标被移动 |
onmouseout | 鼠标从某元素移开 |
onmouseover | 鼠标被移到某元素之上 |
onmouseup | 某个鼠标按键被松开 |
onreset | 重置按钮被点击 |
onresize | 窗口或框架被调整尺寸 |
onselect | 文本被选定 |
onsubmit | 提交按钮被点击 |
onunload | 用户退出页面 |
DOM
DOM是什么
DOM 的全称为:Document Object Model 文档对象模型
每个网页其可以被认为是一个对象在浏览器窗口内部,当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model),文档对象表示将显示在该窗口的HTML文档。文档对象具有参考其他对象,允许访问文件的内容,以和修改各种性质。
HTML DOM 模型被构造为对象的树,如下图:
DOM 可以用来做什么
- JavaScript 能改变页面中的所有 HTML 元素
- JavaScript 能改变页面中的所有 HTML 属性
- JavaScript 能改变页面中的所有 CSS 样式
- JavaScript 能删除已有的 HTML 元素和属性
- JavaScript 能添加新的 HTML 元素和属性
- JavaScript 能对页面中所有已有的 HTML 事件作出反应
- JavaScript 能在页面中创建新的 HTML 事件
DOM的常见操作
- 获取元素:
- 通过 id 找到 HTML 元素
- 通过标签名找到 HTML 元素
- 通过类名找到 HTML 元素
getElementById // document.getElementById("content")
getElementsByTagName // document.getElementsByTagName("table")[0]
getElementsByClassName // document.getElementsByClassName("null-input")[0]
querySelector // 推荐使用
querySelectorAll
- 操作 CSS
- 更改 color
- 操作 border
- 控制 margin
- 注意问题:不能使用
border-color
的形式,而是换成驼峰形式borderColor
tagDiv.onclick = function(){
domDiv.style.width = "200px"
domDiv.style.height = "200px"
domDiv.innerHTML += "hello,world!"
}
- 事件(2种书写方式)
button.onclick = function() {}
注意这里不是驼峰形式button.addEventListener("click", function() {}, useCapture)
BOM
BOM 是什么
BOM(Browser Object Model):浏览器对象模型。
在浏览器中的一些操作都可以使用 BOM 的方法进行编程处理。
比如:刷新浏览器、前进、后退、在地址栏输入 URL 等。
- window
BOM 的顶级对象是:window
, 我们常见的
window.alert();
window.prompt();
window.confirm(); // 两个按钮,分别返回 true 和 false。
通常,我们会省略 window
,写成 alert()
等
- window.onload 页面加载对象
问题: 我们知道,如果将 script 标签放在 head 里面的话,页面加载的时候是先加载的 script 标签,之后才加载 body 里面的标签。如果 script 特别大的话,就很影响用户体验。
解决办法:
- 将 script 标签放在 body 最后。
- 使用
window.onload
事件。
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
window.onload = function () {
document.getElementById("btn").onclick = function () {
alert("haha");
}
}
</script>
</head>
<body>
<input type="button" value="BUTTON" id="btn">
</body>
1、如果不写 window.onload 的话,执行到 document.getElementById("btn") 会报错,因为程序是从上至下执行。
2、window.onload 事件会在页面加载完毕(页面中所有内容、标签、属性以及外部引入的 js文件)时触发。
3、window.onload 可以省略 window。
-
其他 BOM,不太常用,这里简单提一下:
- window.open
- window.location
- window.history
- window.navigator
- window.screen
-
定时器,有2个参数
setInterval(funtion() {}, time)
永久定时器setTimeout(funtion() {}, time)
一次性定时器window.clearInterval(id)
清除定时器window.clearTimeout(id)
清除定时器
具体例子 setInterval:
// setInterval
var intervalId = setInterval(function() {
console.log(123)
}, 1000)
clearInterval(intervalId)
具体例子 setTimeout:
// setTimeout
var timeoutId = setTimeout(function() {
console.log(123)
}, 1000)
clearTimeout(timeoutId)
使用 setTimeout 实现 setItnerval 的效果
function fn() {
console.log(‘set‘)
}
while(true) setTimeout(fn, 1000)
JS中的类和对象
JavaScript中的类和对象是ES6之后才新增的,算是ES6的新特性,在ES6之前,都是通过构造函数和原型去模拟面向对象的类的一个实现机制,下面说一下类和对象的使用,和java中是大致相同 的。
创建对象
在JavaScript中,对象是一组有命名值(属性)集合的容器,常见的创建对象的方法是:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script>
var object=new Object();
object.age=13;
object.lenth=22;
object.height=33;
console.log(object);
</script>
</body>
</html>
最后可以看到相应的打印结果:
可以看到,对象只是一组无序的相关属性和方法的的容器,每个属性都有一个名称和一个值。所有的事务都是对象,例如字符串、数值、数组、函数等。
刚才声明的对象是只有静态信息的,为了使对象具有功能,可以在其中添加自己的函数方法,在JavaScript中,方法是包含Funcation()对象的属性,器目的是对函数内部的对象进行操作。
<script>
var object=new Object();
object.age=13;
object.lenth=22;
object.height=33;
object.getAge=function(){
return this.age;
}
console.log(object.getAge());
</script>
可以看到getAge方法是object对象的一个属性,用于返回object的age属性值。在对象中,如果没有方法属性,那对象就只能用来存储静态信息,其实创建的object对象就是实例化了Object类,声明了一个对象,接下来看一下声明类的方法。
JavaScript中,有9个原生的对象构造函数,JavaScript使用这些对象来构建JavaScript语言,原生对象构造函数是多方面的,它可以生成对象,但也被用于促进语言的编程约定的额形成。例如,函数是Funcation()构造函数创建的对象,但是作为构造函数,使用new关键字调用之后,他们也可以创建爱你其他的对象。
JavaScript预包装了9个原生对象构造函数:
- Number()
- String()
- Boolean()
- Object()
- Array()
- Funcation()
- Date()
- RegExp()
- Error()
JavaScript主要是由这九个对象(以及字符串、数字和布尔原始值)来创建的。
创建类
语法:
class name{
//class body
}
下来做一个demo来展示类的创建和使用,和java之中大多数是差不多的
<html>
<head>
<title>Document</title>
</head>
<body>
<h1>创建类</h1>
<p>创建人类</p>
<script>
// 创建类class 创建一个person类
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
}
var lm=new Person("李明",23);
var zs=new Person("张三",24);
console.log(lm.name+"的年龄是"+lm.age);
console.log(zs);
</script>
</body>
</html>
在浏览器的控制台可以看到输出,输出成功,一个简单的类的创建与使用就完成了
其实在类的创建以及使用的时候,可以看出,基本上和java中类的创建与使用是差不多的,总结为以下几点
- 通过class关键字创建类,类名需要习惯性的大写
- 类里面有个construction函数,是可以接收传递过来的参数,同事返回实例对象
- construction函数是每次在new生成新的实例的时候,就会自动取调用的,如果不能主动声明这个方法的话,在新建实例的时候会默认使用一个无参数的构造方法
- 生成实例的时候,不能省略new
- 最后注意语法规范,创建类的时候,类名厚不加小括号,生成实例的时候类名后要加小括号,个构造函数不需要加function
在类中添加方法
方法也是一种属性,可以在类中添加方法,声明类的实例化对象之后,就可以通过对象去调用声明的方法。
<script>
// 创建类class 创建一个person类
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
say(message){
console.log(message+this.name);
}
}
var lm=new Person("李明",23);
var zs=new Person("张三",24);
lm.say("my name is");
zs.say("my name is")
</script>
写在类中的方法是不需要写funcation的。多个函数之间也不需要用逗号分隔。
类的继承
类的继承其实和java中也大相径庭,JavaScript中继承有六种方式
先创建一个父类
// 创建类class 创建一个父类
class Father{
constructor(name,age){
this.name=name;
this.age=age;
}
say(){
return this.name + "爸爸的年龄是" + this.age;
}
}
写一个子类继承
class Son extends Father{
constructor(name,age){
super(name, age); //调用了父类中的构造函数,将参数传至父类中的say方法中
}
}
var son=new Son(‘十三‘, 24);
alert(son.say()); //十三爸爸的年龄是24
可以看到,继承后,子类可以拥有父类的所有属性,就可以调用say方法了,并且可以通过super关键字讲参数传入say()方法中。
下面改写一下子类,也加一个自己的say()方法
class Son extends Father{
constructor(name,age){
super(name, age); //调用了父类中的构造函数,将参数传至父类中的say方法中
//constructor里面的this指向的是新创建的实例对象
this.name=name;
this,age=age;
}
say() {
console.log(this.name + "的年龄是" + this.age);
return this.name + "的年龄是" + this.age;
}
fatherSay(age) {
super.age= age; //将父类的参数传入
return super.say();//调用父类方法并返回
}
}
var son=new Son(‘十三‘, 24);
console.log(son.say()); //十三的年龄是24
//可以看到子类执行的时候执行了自己的say()方法,在子类执行自己的构造函数的时候,会默认执行参数的传参操作
继承中属性或者方法的的查找原则--就近原则
- 继承中,如果实例化子类输出一个放大,先看看子类中有没有这个方法,如果有就先执行子类的方法
- 继承中,如果子类没有,就会去查找父类有没有这个方法,如果有,就会执行父类这个方法
子类继承了父类之后,除了可以使用继承的属性和方法之外,还可以定义自己的属性与方法。这里不多赘述。
注意点:
- 在ES6中是没有变量提升的,所以必须先定义类,才能进行实例化
- 类中的公有的属性和方法一定要加this才能进行使用。
- 类里面的this指向,一般来说方法中的this都指向方法的调用者,比如说constructor里面的this指向的是新创建的实例对象
jQuery
jQuery 是什么
jQuery库可以通过一行简单的标记被添加到网页中去
什么是 js 库?
JavaScript 开发的过程中,处理浏览器的兼容很复杂而且很耗时,于是一些封装了这些操作的库应运而生。这些库还会把一些常用的代码进行封装。
把一些常用到的方法写到一个单独的 js 文件,使用的时候直接去引用这js文件就可以了,这个 js 文件就是 JavaScript 库。
什么是jQuery?
jQuery 就是一个 JavaScript 函数库,它可以通过一行简单的标记被添加到网页中去。没有什么特别的。里面封装了一大堆的方法方便我们的开发,因此我们学习jQuery,其实就是学习jQuery这个 js 文件中封装的一大堆方法。
jQuery包含的功能
jQuery就是一个js库,基本上就是为了更方便的完成js要实现的功能,极大地简化了JavaScript的编程,大致如下:
- HTML元素选取
- HTML元素操作
- CSS操作
- HTML事件函数
- JavaScript特效和动画
- HTML DOM遍历和修改
- AJAX
- Utilities(工具类)
如何引入jQuery
-
jQuery 库位于一个 JavaScript 文件中,其中包含了所有的 jQuery 函数,可以从jquery.com下载jQuery库,然后引入页面
<head> <script type="text/javascript" src="jquery.js"></script> </head> //请注意,<script> 标签应该位于页面的 <head> 部分。
-
从CDN中载入jQuery,谷歌、百度、微软等服务器中都有jQuery,直接引入就可以了
使用 Google 的 CDN
<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs /jquery/1.4.0/jquery.min.js"></script> </head>
使用 Microsoft 的 CDN
<head> <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery /jquery-1.4.min.js"></script> </head>
使用 百度 的 CDN
<head> <script type="text/javascript" src="http://lib.baidu.com/jquery /jquery-1.4.min.js"></script> </head>
jQuery的语法
jQuery 语法是为 HTML 元素的选取编制的,可以对元素执行某些操作。
基础语法是:$(selector).action()
- 美元符号定义 jQuery
- 选择符(selector)“查询”和“查找” HTML 元素
- jQuery 的 action() 执行对元素的操作
jQuery选择器
jQuery元素选择器
jQuery 使用 CSS 选择器来选取 HTML 元素的。
基础选择器
<div id="test" class="test">hello world</div>
// id 选择器
var id = $("#test")
console.log(id) // "hello world"
// 类选择器
var cls = $(".test")
console.log(cls) // "hello world"
// 标签选择器,选择所有符合条件的标签
var div = $("div")
console.log(div) // "hello world"
复合选择器
<div id="test">
<p>hello,world</p>
<span>hello,sss</span>
</div>
$("div,p,span") // 并集选择器,获取多个元素
$("div#test") // 交集选择器,获取 所有的id 为 test 的div元素
$("div p") // 后代选择器,获取 div 的后代元素 p
$("div:odd") // 获取第奇数个 div 标签
$("div:even") // 获取第偶数个 div 标签
jQuery 属性选择器
jQuery 使用 XPath 表达式来选择带有给定属性的元素。
$("[href]") 选取所有带有 href 属性的元素。
$("[href=‘#‘]") 选取所有带有 href 值等于 "#" 的元素。
$("[href!=‘#‘]") 选取所有带有 href 值不等于 "#" 的元素。
$("[href$=‘.jpg‘]") 选取所有 href 值以 ".jpg" 结尾的元素。
jQuery CSS 选择器
jQuery CSS 选择器可用于改变 HTML 元素的 CSS 属性。
有两种写法,链式写法和键值对写法
//链式写法
$("#father").css("border","1px solid black").css("color", "red")
//键值对写法
var divCss = {
border: "1px solid black",
color: "red"
}
$("#father").css(divCss)
jQuery事件
常用事件方法
//JS中事件有两种写法,可以和jQuery中做一下对比
// 对比 js 的事件1
button.onclick = function() {}
// 对比 js 的事件2
button.addEventListener("click", function() {}, false)
// jQuery 常用的事件
$(document).ready(function) //文档加载完成时候出发的事件
$("#btn").click(function) //获取点击事件
$("#btn").dbclick(function) //获取双击事件
$("span").mouseenter(function) //鼠标指针进入(穿过)元素
$("span").mouseleave(function) //鼠标离开元素
$("span").hover(function) //鼠标悬停
$("span").focus(function) // 触发或将函数绑定到被选元素的获得焦点事件
$("span").blur(function) // 触发或将函数绑定到被选元素的失去焦点事件
事件的绑定与解除
bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数。
unbind() 方法为被选元素解除一个或多个事件处理程序
在jquery1.7之后,官方是建议使用on和off来替代bind和unbind的。是都可以使用的,效果以及语法都一样
基本的语法是:
$(selector).bind(event,data,function)
$(selector).unbind(event,data,function)
event: 必需。规定添加到元素的一个或多个事件。由空格分隔多个事件。必须是有效的事件。
data: 可选。规定传递到函数的额外数据。
function:必需。规定当事件发生时运行的函数。
示例:
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").bind("click",hide); //将事件绑定到元素上
$("button").unbind("click"); //将事件解除绑定,不加function参数的话会解除该元素上所有的click
});
function hide(e){
$("p").slideToggle();
}
</script>
</head>
<body>
<p>这是一个测试类</p>
<button>请点击这里</button>
</body>
</html>
事件的目标
event
标准Event属性:
属性和方法 | 描述 |
---|---|
bubbles | 返回布尔值,指示事件是否是起泡事件类型。 |
cancelable |
返回布尔值,指示事件是否可拥可取消的默认动作。 |
currentTarget |
返回其事件监听器触发该事件的元素。 |
eventPhase | 返回事件传播的当前阶段。 |
target |
返回触发此事件的元素(事件的目标节点)。 |
timeStamp | 返回事件生成的日期和时间。 |
type |
返回当前 Event 对象表示的事件的名称。 |
initEvent() | 初始化新创建的 Event 对象的属性。 |
preventDefault() |
通知浏览器不要执行与事件关联的默认动作。 |
stopPropagation() |
不再派发事件。 |
事件的冒泡
// 方法1 event.stopPropagation() 阻止父级的冒泡事件
// 方法2 event.stopImmediatePropagation() 阻止所有的冒泡事件
// 方法3 return false; //相当于程序直接返回,事件被终止
自定义事件
jQuery.Event("MyEventName");
${"#btn"}.trrigger(e);
AJAX
Ajax
ES6
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的新一代版本标准,2015.06 发版。
ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。
ES6主要有以下一些特性
定义变量
let
let和const是ES6中新增加的两个关键字,用来声明变量,在此之前声明变量只有var,let和const都是块级作用域。
let 允许创建块级作用域,ES6 推荐在函数中使用 let 定义变量,而非 var:
{
var a = 2;
let b = 3;
console.log(a); // 3
}
console.log(a); // 2
console.log(b); // ReferenceError: b is not defined
const
同样在块级作用域有效的另一个变量声明方式是 const,它可以声明一个常量。ES6 中,const 声明的常量类似于指针,它指向某个引用,也就是说这个常量并非一成不变的,如:
{
const arr = [5,6];
arr.push(7);
console.log(arr); // [5,6,7]
arr = 10; // Assignment to constant variable.
}
有几个点需要注意:
- let 关键词声明的变量不具备变量提升(hoisting)特性
- let 和 const 声明只在最靠近的一个块中(花括号内)有效
- 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
- const 在声明时必须被赋值
解构赋值
ES6中可以按照一定的模式从数组和对象中提取出来值,对变量进行赋值,这种就是解构
//数组解构
let [a,b,c] =[1,2,3];
a //1
b //2
c //3
//数组嵌套赋值
let [a, [[b], c]] = [1, [[2], 3]];
a // 1
b // 2
c // 3
//上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
//对象解构
let name=‘Tom‘;
let age=‘13‘;
let student={name,age};
student //{name: "Tom", age: "13"}
//对象解构
let student={name: "Tom", age: "13"};
let{name,age}=student;
name //Tom
age //13
//数组解构和对象解构差不多,只要模式匹配都可以进行解构赋值
这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值.
还有就是如果等号两边模式不相等,还会有省略赋值和不定参数赋值
//省略赋值
let [ , , c] = [1, 2,3];
c // 3
let [a, , c] = [1, 2, 3];
a // 1
c // 3
//不赋值的位置可以不用变量接收,直接用空白代替就可以了
//不定参数赋值,使用...来表示不定参数,...是扩展运算符,可以将一个数组转成用逗号分隔的形式
let [a, ...b] = [1, 2, 3, 4];
a // 1
b // [2, 3, 4]
let [a,b, ...c] = [‘a‘];
a // "a"
b // undefined
c // []
如果解构不成功,变量的值就等于undefined
解构不成功说的是右边没有左边对应的值,比如说
let [a,b,c] = [1, 2];
a // 1
b // 2
c // undefined
//c就是解构不成功,因为右边的数组里没对应的值
还有一种是左边没有右边对应的值,这种是不完全解构,是可以解构成功的
let [a,b] = [1, 2,3];
a // 1
b // 2
函数问题
箭头函数(Arrow Functions)
ES6 中允许使用“ =>”来定义函数,使用括号包裹参数,跟随一个 =>,紧接着是函数体,不需要function关键字也可以省略return关键字:
var getPrice = a => a+1;
//等价于
var getPrice = function() {
return a+1;
};
这个例子中的 getPrice 箭头函数采用了简洁函数体,它不需要 return 语句,下面这个例子使用的是正常函数体:
let arr = [‘apple‘, ‘banana‘, ‘orange‘];
let breakfast = arr.map(fruit => {
return fruit + ‘s‘;
});
console.log(breakfast); // apples bananas oranges
当然,箭头函数不仅仅是让代码变得简洁,函数中 this 总是绑定总是指向函数定义时候所在的上下文对象,而不是函数执行之后调用它的上下文对象。具体可以看看下面几个例子:
function Person() {
this.age = 0;
setInterval(function growUp() {
// 在非严格模式下,growUp() 函数的 this 指向 window 对象
this.age++;
}, 1000); //每秒给age加一
}
var person = new Person();
我们经常需要使用一个变量来保存 this,然后在 growUp 函数中引用:
function Person() {
var self = this;
self.age = 0;
setInterval(function growUp() {
self.age++;
}, 1000);
}
而使用箭头函数可以省却这个麻烦:
function Person(){
this.age = 0;
setInterval(() => {
// |this| 指向 person 对象
this.age++;
}, 1000);
}
var person = new Person();
函数参数默认值
ES6 中允许你对函数参数设置默认值:
let getFinalPrice = (price, tax=0.7) => price + price * tax;
getFinalPrice(500); // 850
模板字符串
模板字符串是增强版的字符串,会用反引号(`)来标识字符串,除了可以当做普通的字符串之外,还可以用来定义多行的字符串,以及在字符串中嵌入变量。
const str1= `正常的字符串`;
const str2= `多行的
字符串`;
let name=‘十三‘;
const str3=`hello,${name}`;
set和map
Map 和 WeakMap
ES6 中两种新的数据结构集:Map 和 WeakMap。事实上每个对象都可以看作是一个 Map。
创建map的方法:
- 使用构造函数的方式创建一个实例
- 参数是个数组,数组的每一项都是一个数组,这个数组有两项,分别对应map的key和value,这个就和java中的map的概念一样了
- 在 Map 中,任何类型都可以作为对象的 key
如:
var map = new Map();
var keyString = "a string",
keyObj = {},
keyFunc = function () {};
// 设置值
map.set(keyString, "value 与 ‘a string‘ 关联");
map.set(keyObj, "value 与 keyObj 关联");
map.set(keyFunc, "value 与 keyFunc 关联");
map.size; // 3
// 获取值
map.get(keyString); // "value 与 ‘a string‘ 关联"
map.get(keyObj); // "value 与 keyObj 关联"
map.get(keyFunc); // "value 与 keyFunc 关联"
//删除值
map.delete(keyString);
//查看是否存在
map.has(keyString); //false
//清空map
map.clear();
//遍历map
map.forEach((key,val,map)=> {
//val :内容
//key :键值
//map: 原Map实例
//参数顺序不能乱,第一个代表内容,第二个是键值,第三个是实例
});
for(var key of map.keys()){
//遍历键值
}
for(var val of map.values()){
//遍历内容
}
for(var [key,val] of map.entries){
//遍历键值和内容
}
WeakMap
WeakMap 就是一个 Map,只不过它的所有 key 都是弱引用,意思就是 WeakMap 中的东西垃圾回收时不考虑,使用它不用担心内存泄漏问题。
另一个需要注意的点是,WeakMap 的所有 key 必须是对象。它只有四个方法 delete(key),has(key),get(key) 和set(key, val):
let w = new WeakMap();
w.set(‘a‘, ‘b‘);
// Uncaught TypeError: Invalid value used as weak map key
var o1 = {},
o2 = function(){},
o3 = window;
w.set(o1, 37);
w.set(o2, "azerty");
w.set(o3, undefined);
w.get(o3); // undefined, because that is the set value
w.has(o1); // true
w.delete(o1);
w.has(o1); // false
Set 和 WeakSet
Set 对象是一组不重复的值,重复的值将被忽略,值类型可以是原始类型和引用类型:
let mySet = new Set([1, 1, 2, 2, 3, 3]);
mySet.size; // 3
mySet.has(1); // true
mySet.add(‘strings‘);
mySet.add({ a: 1, b:2 });
可以通过 forEach 和 for...of 来遍历 Set 对象:
mySet.forEach((item) => {
console.log(item);
// 1
// 2
// 3
// ‘strings‘
// Object { a: 1, b: 2 }
});
for (let value of mySet) {
console.log(value);
// 1
// 2
// 3
// ‘strings‘
// Object { a: 1, b: 2 }
}
Set 同样有 delete() 和 clear() 方法。
WeakSet
类似于 WeakMap,WeakSet 对象可以让你在一个集合中保存对象的弱引用,在 WeakSet 中的对象只允许出现一次:
var ws = new WeakSet();
var obj = {};
var foo = {};
ws.add(window);
ws.add(obj);
ws.has(window); // true
ws.has(foo); // false, foo 没有添加成功
ws.delete(window); // 从结合中删除 window 对象
ws.has(window); // false, window 对象已经被删除
Promise
ES6 对 Promise 有了原生的支持,一个 Promise 是一个等待被异步执行的对象,当它执行完成后,其状态会变成 resolved 或者rejected。
var p = new Promise(function(resolve, reject) {
if (/* condition */) {
// fulfilled successfully
resolve(/* value */);
} else {
// error, rejected
reject(/* reason */);
}
});
每一个 Promise 都有一个 .then 方法,这个方法接受两个参数,第一个是处理 resolved 状态的回调,一个是处理 rejected 状态的回调:
p.then((val) => console.log("Promise Resolved", val),
(err) => console.log("Promise Rejected", err));
Class
JavaScript中的类和对象是ES6之后才新增的,算是ES6的新特性,在ES6之前,都是通过构造函数和原型去模拟面向对象的类的一个实现机制,下面说一下类和对象的使用,和java中是大致相同 的。
迭代器
迭代器允许每次访问数据集合的一个元素,当指针指向数据集合最后一个元素是,迭代器便会退出。它提供了 next() 函数来遍历一个序列,这个方法返回一个包含 done 和 value 属性的对象。
ES6 中可以通过 Symbol.iterator 给对象设置默认的遍历器,无论什么时候对象需要被遍历,执行它的 @@iterator 方法便可以返回一个用于获取值的迭代器。
数组默认就是一个迭代器:
var arr = [11,12,13];
var itr = arr[Symbol.iterator]();
itr.next(); // { value: 11, done: false }
itr.next(); // { value: 12, done: false }
itr.next(); // { value: 13, done: false }
itr.next(); // { value: undefined, done: true }
你可以通过 Symbol.iterator自定义一个对象的迭代器。
Symbol
Symbol 是一种新的数据类型,它的值是唯一的,不可变的。ES6 中提出 symbol 的目的是为了生成一个唯一的标识符,不过你访问不到这个标识符:
var sym = Symbol( "some optional description" );
console.log(typeof sym); // symbol
注意,这里 Symbol 前面不能使用 new 操作符。
如果它被用作一个对象的属性,那么这个属性会是不可枚举的:
var o = {
val: 10,
[ Symbol("random") ]: "I‘m a symbol",
};
console.log(Object.getOwnPropertyNames(o)); // val
如果要获取对象 symbol 属性,需要使用Object.getOwnPropertySymbols(o)。
以上是关于JavaScript基础学习的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段12——JavaScript的Promise对象