js是动态的、弱类型的、解释型、多用于浏览器的脚本语言。
用于服务端的node.js.
浏览器端的js可以调用浏览器的各种对象,可以进行Dom/BOM操作。
服务端的js可以进行io、调用数据库等操作。
ECMAScript是一种规范,JS实现了该规范,前后端都适用。
TypeScript是一种在JS上进行增强的语言,多数功能也实现了ES。
一、浏览器中js的功能
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)
浏览器对象模型(Browser Object Model (BOM))允许 JavaScript 与浏览器对话
通过这两个模型,js能动态操作页面的所有内容和浏览器的各种功能。
HTML DOM 模型被结构化为对象树。
如通过Dom中某button对象的属性,触发函数,与Bom对象window进行交互。
<button onclick="alertTitle()">弹出</button>
<script>
document.writeln("写入")
document.write("数据")
function alertTitle(){
window.alert("Hello Alert")
}
</script>
<!--window.alert中window可以省略,默认是window对象-->
<script src="xx.js"></script>
js可以通过script标签直接嵌入html中使用,也可以从外部引入js文件使用
二、使用
001、Dom
通过document对象可以获取各个dom对象,并且动态修改。
document可以通过id、class、nodename等各种方式获取节点对象。
<h1 id="h_id">hello 我是标签</h1>
<script>
document.write("nice","ok")
document.getElementById("h_id").style="color:red"
</script>
002、Bom
常用的浏览器对象有Window,直接使用即可。
使用浏览器提供的交互功能在本地存储一个数据,再打印到浏览器控制台。
localStorage经常用来保存后台传来的token。
IndexDB
localStorage.setItem("name","Tom Blue")
console.log(localStorage.name)
003、变量
js是动态语言,使用var声明变量,当然不用var也可
var v1="hello"
console.log(v1)
v2="world"
console.log(v2)
hello
world
变量提升
变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。
JavaScript 只有声明的变量会提升,初始化的不会
console.log(v1)
var v1="ok"
此时显示undefined,v1的初始值不会被提示到顶部。
console.log(v2)如果直接输出v2会报错,因为没有v2
let、const
let是ES中推荐的定义方式,默认情况下javascript中并没有块级(block)作用域,let则是块级定义域
let 关键词声明的变量不具备变量提升(hoisting)特性
let 和 const 声明只在最靠近的一个块中(花括号内)有效
当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
const 在声明时必须被赋值
let v=1;
const V_NAME="const"
004、运算符
多数语言运算符都类似,挑几个js中比较特殊的运算符。
==只比较值,===比较值和类型。
let v1="1"
let v2=1
console.log(v1==v2) true
console.log(v1===v2) false
比较运算符
运算符 | 描述 |
---|---|
== | 等于 |
=== | 等值等型 |
!= | 不相等 |
!== | 不等值或不等型 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
? | 三元运算符 |
类型运算符
运算符 | 描述 |
---|---|
typeof | 返回变量的类型。 |
instanceof | 返回 true,如果对象是对象类型的实例。 |
005、函数
函数是编程语言的基本功能,在js中发挥很大的作用,Js的面向对象功能也能通过函数模拟。
//使用关键字即可声明函数。
function print_msg(info){
console.log("info : "+info)
}
//js语法比较松散,不检查参数,多了少了也无所谓
print_msg("打印消息")
print_msg("打印消息","ok")
print_msg()
info : 打印消息
info : 打印消息
info : undefined
//Es中扩展了功能,可以接受多参数进入
function print_msg(...info){
console.log("info : "+info)
}
事件
事件就是发生的事情,也可以说是传递消息的机制。
下面是一些常见的HTML事件的列表:
onchange HTML 元素改变
onclick 用户点击 HTML 元素
onmouseover 用户在一个HTML元素上移动鼠标
onmouseout 用户从一个HTML元素上移开鼠标
onkeydown 用户按下键盘按键
onload 浏览器已完成页面的加载
<!--1、事件被触发后就会执行相应功能-->
<button onclick="this.innerHTML=Date()">现在的时间是?</button>
<!--2、事件常与函数结合-->
<button onclick="alertTitle()">弹出</button>
<script>
function alertTitle(){
window.alert("Hello Alert")
}
</script>
<!--3、通过addEventListener() 方法用于向指定元素添加事件句柄-->
<button id="myBtn">弹出</button>
<script>
document.getElementById("myBtn").addEventListener("click", function(){
alert("hello")
});
</script>
闭包
js、go、python等语言中都有闭包,所以闭包到底是不是bug。
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。
直观的说就是形成一个不销毁的栈环境。
var add=function(){
var id=0;
return function(){
id+=1;
console.log(id)
}
}();//此处执行了方法,返回了一个函数
add();1 //此时的add是内部的函数,引用了父函数的id变量
add();2//所以id变量不能被销毁,且只能通过add处理
add();3//id是在匿名函数中定义的,所以此时相当于私有变量
箭头函数、this
面向对象语言中 this 表示当前对象的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
在方法中,this 表示该方法所属的对象。
如果单独使用,this 表示全局对象。
在函数中,this 表示全局对象。
在函数中,在严格模式下,this 是未定义的(undefined)。
在事件中,this 表示接收事件的元素。
类似 call() 和 apply() 方法可以将 this 引用到任何对象。
//Es6中提供了箭头函数,可以简化操作
var hi=()=>{
return 10;
}
var hi=()=>10
//在函数中,this通常指向全局对象window,箭头函数中的this指向自身
006、数据类型
字符串值String,数值Number,布尔值Boolean,数组Array,对象Object。
面向对象的角度来看,一切都可以归于对象。
js中的数值型只有一种,可以是整形,也可以是浮点型.
let n1=12
n2=11.2
n3=123e5
console.log(n1)12
console.log(n2)11.2
console.log(n3)12300000
数组
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";
var cars=new Array("Saab","Volvo","BMW");
var cars=["Saab","Volvo","BMW"];
这三种方式产生的数组是一样的,使用new关键字创建数组。
push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素,成功返回删除元素的值
shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除
后想要在原位置替换的值(可选)
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() 将数组倒序,成功返回倒序后的数组
n=cars.push("BYD");
console.log(n)
console.log(cars)
cars.sort()
console.log(cars)
4
[ 'Saab', 'Volvo', 'BMW', 'BYD' ]
[ 'BMW', 'BYD', 'Saab', 'Volvo' ]
对象
对象使用{}表示,js使用面向对象进行描述。
js中属性名可用双引号包裹
var car = {
type:"Fiat",
"model":500,
color:"white",
//方法
run:function(){
console.log("run....")
}
};
car.info=function(){
console.log(this.color+this.type+this.model)
}
console.log(car)
car.run()
car.info()
{ type: 'Fiat', model: 500, color: 'white', run: [Function: run] }
run....
whiteFiat500
js中对象的定义有多种方式,以上直接赋值的方式只能使用一次。
可以使用函数声明对象,模拟面向对象,有构造器、类方法等。
使用ES6提供的class、constructor关键字创建对象,和java、python等十分相似。
function Car(type,color){
//使用函数模拟类,this关键字在这里指向当前对象,不使用this则属性不和对象挂钩
this.type=type;
this.color=color;
this.run=function(){
console.log(color+type+" run....")
}
}
//使用new可以创建对象
var c=new Car("BYD","yellow");
//对象方法,只属于该对象
c.info=function(){
console.log(this.color+this.type)
}
//实例方法,挂载到原型链上,所有实例对象都可使用
Car.prototype.hi=function(){
console.log("hi")
}
//类方法、只允许类调用
Car.hello=()=>{
console.log("Hello")
}
ES提供的class、constructor关键字使js对象可以像java等语言一样声明对象,不过这只是语法糖。
class Person {
constructor(names,age,word){
//此处的word只是函数参数,不属于整个对象,其他方法中无效
this.names=names;
this.age=age;
console.log("name:"+names+" age:"+age+" word:"+word)
}
disPlay(){
//此处可以获取到下文挂到原型链上的word属性
console.log("name:"+this.names+" age:"+this.age+" word:"+this.word)
}
}
//这里将word挂到原型链上,因此对象也有了word属性
Person.prototype.word="ES";
//Person.word="SSS";这相当于是类属性了,只有类能访问
var p=new Person("jack",10,"ES6面向对象");
p.disPlay();
name:jack age:10 word:ES6面向对象
name:jack age:10 word:ES
原型与原型链
每个函数都有一个 prototype 属性
每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型。
每个原型都有一个 constructor 属性指向关联的构造函数 实例原型指向构造函数
Es的class只是语法糖,最终也解释成函数,如下:
console.log(Person.prototype==p.__proto__) //true
console.log(p.__proto__.constructor==Person) //true
007、严格模式
"use strict" 指令在 JavaScript 1.8.5 (ECMAScript5) 中新增。
它不是一条语句,但是是一个字面量表达式,在 JavaScript 旧版本中会被忽略。
"use strict" 的目的是指定代码在严格条件下执行。
严格模式下你不能使用未声明的变量。
"use strict";
x = 3.14; // 报错 (x 未定义)
008、流程
判断、循环
var a=100;
if(a>10){
console.log(`a: ${a}`) //Es6提供的字符串模板插值
}else if(a>20){ //顺序执行,此处已经跳过
console.log(`a: ${a}`)
}else{
console.log(`a: ${a}`)
}
//while循环
while(a>=100){
a-=10;
console.log(`a: ${a}`)
}
//for循环
for(;a<100;a++){
console.log(a)
}
switch语句
var d=new Date().getDay();
var x;
switch (d) //根据d的值选择执行case
{
case 0:x="今天是星期日";
break; //遇到则结束代码块,否则继续向下全部执行
case 1:x="今天是星期一";
break
case 2:x="今天是星期二";
break
case 3:x="今天是星期三";
break
case 4:x="今天是星期四";
break;
case 5:x="今天是星期五";
break;
default:x="今天是星期六";
}
console.log(`${x}`)
continuereak:下一迭代结束代码
009、回调函数
//回调函数在父函数执行时被调用,所以叫回调,在js中常用
function call(callback,msg){
console.log(msg)
callback();//传入的参数是个函数
}
//直接传入一个匿名函数作为回调函数
call(function(){
console.log("这是回调函数")
},"Hello Callback Func")
010、常用对象
Date对象
Date.prototype.format = function(fmt){
var o = {
"M+" : this.getMonth()+1, //月份
"d+" : this.getDate(), //日
"h+" : this.getHours(), //小时
"m+" : this.getMinutes(), //分
"s+" : this.getSeconds(), //秒
"q+" : Math.floor((this.getMonth()+3)/3), //季度
"S" : this.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt)){
fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o){
if(new RegExp("("+ k +")").test(fmt)){
fmt = fmt.replace(
RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
return fmt;
}
console.log( new Date().format("yyyy-MM-dd hh:mm:ss"))
console.log( new Date().format("yyyy年-MM月-dd日"))
console.log( new Date().format("yyyy/MM/dd"))
数组对象
push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素,成功返回删除元素的值
shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除
后想要在原位置替换的值(可选)
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() 将数组倒序,成功返回倒序后的数组
concat()
join()
toString()
map()通过指定函数处理数组的每个元素,并返回处理后的数组。
forEach()数组每个元素都执行一次回调函数。
filter()检测数值元素,并返回符合条件所有元素的数组。
fill()通过给定数据填充数组
from() 类方法,通过字符串返回数组
var arr=new Array("hello","world","Good","Nice");
//map
var s=arr.map(msg=>msg+"001")
console.log(s) [ 'hello001', 'world001', 'Good001', 'Nice001' ]
//forEach
arr.forEach((item,index,arr)=>{
console.log(item)
})
//filter
var s2=arr.filter(msg=>{
return msg.length>4
})
console.log(s2) [ 'hello', 'world' ]
//Array.from
console.log(Array.from("ok"))
//fill
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.fill("food", 2, 4);
console.log(fruits)[ 'Banana', 'Orange', 'food', 'food' ]
Math对象
round()四舍五入,ceil()/floor()向上、下进行舍入
random()返回 0 到 1 之间的随机数。
max(...) 返回最大参数
min(...)
pow(x,y)返回x的y次幂
abs()绝对值
sqrt()平方根
//根据上下限生成随机数:
var rand = (min,max) => Math.round(Math.random()*(max-min))+min;
//根据长度随机字符串
function randChar(length){
characters="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
//length为所需长度,characters为所包含的所有字符,默认为字母+数字。
characters=characters.split("");//分割字符。
result="";//返回的结果。
while(result.length<length) result+=characters[Math.round(Math.random()*characters.length) - 1];
return result;
}
//随机从数组中取出一个
Array.prototype.pick=function(){
return this[(this.length?Math.round(Math.random()*(this.length-1)):undefined)];
}
String对象
属性:
length
prototype
constructor
方法:
charAt()
charCodeAt()
concat()
fromCharCode()
indexOf()
lastIndexOf()
match()
replace()
search()
slice()
split()
substr()
substring()
toLowerCase()
toUpperCase()
valueOf()
var str="Hello world"
console.log(str.length) 11
console.log(str.split(" ")) [ 'Hello', 'world' ]
console.log(str.slice(0,3)) Hel
模块化
Js的模块体系主要有AMD、CommonJs、ES6,前者用于浏览器,后者用于服务器。
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
在CommonJs中,使用exports.xx=yy导出,使用require('xx')导入
//ex.js
var hi=function(){
console.log("hi hi hi ")
}
exports.hi=hi //导出hi
//导入,想当于把文件暴露的模块全部导入
x=require("./ex")
x.hi() //这里也要和导出文件对应
Es6的模块话使用export,import
export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系,不可导出变量
import导入必须和导出变量名一致,当使用export default时无需
//Es模块如果使用在服务端,可能会有不兼容的问题,可以把文件名改为x.mjs或者在配置文件中处理
export {hi}; //导出
import {hi} from "ex" //导入
JSON
JSON 英文全称 JavaScript Object Notation
JSON 是用于存储和传输数据的格式,通常用于服务端向网页传递数据,与语言无关,序列化友好。
JSON还用于配置信息,不过多用于前端。
JSON语法:
数据为 键/值 对,键(字符串)必须使用双引号(单引号不行)。
键值用分号隔开,
数据由逗号分隔。
大括号保存对象
方括号保存数组
JSON组成:
对象、数组、字符串、数值,布尔值
//JS提供的处理json的函数
JSON.parse() 用于将一个 JSON 字符串转换为 JavaScript 对象。
JSON.stringify() 用于将 JavaScript 值转换为 JSON 字符串。
//这是一个js对象,虽然和JSOn格式一样
var json={
"name":["Tom","JIm","Sally"],
"age":18,
"desc":"All are students"
}
console.log(json)
console.log(JSON.stringify(json))
console.log(JSON.parse(JSON.stringify(json)))
{ name: [ 'Tom', 'JIm', 'Sally' ], age: 18, desc: 'All are students' }
{"name":["Tom","JIm","Sally"],"age":18,"desc":"All are students"}
{ name: [ 'Tom', 'JIm', 'Sally' ], age: 18, desc: 'All are students' }
异步方法
AJax
三、Es语法
001、for ..of、for ... in、iterator
//forEach、map等方法可以方便的操作数组,如下
arr=[10,23,12,34]
arr.forEach(e=>{
console.log(e)
})
//es6也提供了增强for和迭代器
//for ...of获取到元素
for(var e of arr){
console.log(e)
}
//for...in 获取到属性
for(var i in arr){
console.log("属性: "+i,"值: "+arr[i])
}
//迭代器,其中value表示当前的数据的值,done是一个布尔值,表示遍历是否结束。
var iter=arr[Symbol.iterator]()
console.log(iter.next().value)
var str ="hellonice";
var it=str[Symbol.iterator]();
console.log(it.next())
//支持迭代器的原生类型:
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象
002、Promise
Promise 是异步编程的一种解决方案,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
var ok=new Promise(function(resolve,reject){
var i=10;
if(i>1){
resolve("hello")
}else{
reject("nice")
}
})
//异步
ok.then(res=>{
console.log(res)
})
003、Generator
//使用*表示
function *outMsg(){
console.log("nice")
yield "one";
yield "Two";
return "three";
}
var msg=outMsg();//返回一个迭代器,value为yield的值
console.log(msg.next())