基本概念
JavaScript是世界上最流行的脚本语言,因为你在电脑、手机、平板上浏览的所有的网页,以及无数基于HTML5的手机App,交互逻辑都是由JavaScript驱动的。简单地说,JavaScript是一种运行在浏览器中的解释型的编程语言。在Web世界里,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
前端与后端
- 前端:针对浏览器的开发,代码在浏览器运行。前端开发模式:MVC -> MVVM。
- 后端:针对服务器的开发,代码在服务器运行。后端开发模式:MVC。
前端架构
- 传统架构。
- SPA:Single-page-application,单页架构。
- 前后端分离:Ajax->前端应用兴起;智能手机->多终端支持;后端:REST形式接口;前端:消费后端提供的数据;通信协议:http。
前端开发
1. 前端开发模式的根本变化
- Node环境下开发
- 大量使用服务器端工具
- 引入持续集成等软件工程的标准流程
- 开发完成后,编译成浏览器可以运行的脚本,放上CDN。
2. 全栈技能
- 传统前端技能:HTML、JavaScript、CSS
- 一门后端语言
- 移动端开发:IOS/Android/HTML5
- 其他技能:数据库、HTTP等等
3. 未来软件的特点
联网、高并发、分布式、跨终端。
Node.js
2009年,Node项目诞生,它是服务器上的JavaScript运行环境。
Node的意义
- JavaScript成为服务器脚本语言,与Python和Ruby一样
- JavaScript成为唯一的浏览器和服务器都支持的语言
- 前端工程师可以编写后端程序了
JavaScript基础
网页的生成
- HTML代码转化为DOM
- CSS代码转化为CSSOM(CSS Object Model)
- 结合DOM和CSSOM,生成一棵渲染树,包含每个节点的视觉信息
- 生成布局(layout),将所有渲染树的所有节点进行平面整合
- 将布局绘制(paint)在屏幕上
渲染render
- 生成布局flow和绘制paint这两步全称为渲染
- 网页生成时至少渲染一次,用户访问过程中会不断重新渲染(修改DOM、修改样式表、用户事件)
- 重新渲染包含:重排(reflow)和重绘(repaint),但重绘不一定需要重排,重排必定重绘
JavaScript应用场景
- 网页特效
- 服务端开发
- 命令行工具
- 桌面程序(Electron)
- APP(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
JavaScript组成
- ECMAScript:JavaScript的核心,定义了JavaScript的语法规范
- BOM:浏览器对象模型,操作浏览器功能的API集合,通过BOM可以操作浏览器窗口,比如:弹出框、控制浏览器跳转、获取分辨率等
- DOM:文档对象模型,操作页面元素的API集合,DOM把HTML看做是文档树,通过DOM提供的API可以对树上的节点进行操作
JavaScript数据类型
简单数据类型:
Number、String、Boolean、Undefined和Null
1. Number类型
前面添加“-”符号表示负数;设置为NaN表示非数值;添加“+”表示正数。数值型包含整数、小数、以及特殊值NaN(Not a Number 不是一个数字,但是他是数字类型,可以理解为计算错误)。NaN是一个全局对象的属性,它是初始值就是NaN与数值型中的特殊值NaN一样,都表示非数字Not a Number。数值判断:NaN:not a number,NaN与任何值都不相等,包括它本身。isNaN:is not a number。
2. String类型
所有的用引号包括起来的(单引号、双引号)汉字一定是字符串类型。在单引号里面想显示单引号用转义字符“\”(反斜杠)。
- 字符串长度:length属性用来获取字符串的长度。
- 字符串拼接:使用"+"连接。两边只要有一个是字符串,那么"+"就是字符串拼接功能;两边如果都是数字,那么就是算术功能。
3. Boolean类型
- true和false区分大小写
- 计算机内部存储:true为1,false为0
4. Undefined和Null
- undefined表示一个声明了没有赋值的变量,变量只声明的时候值默认是undefined
- null表示一个空,变量的值如果想为null,必须手动设置
- null和Undefind与空字符串(' ')和0都不相等。
5. 复杂数据类型
Object
6. 获取变量类型
- typeof
- 数据类型两种检测方式:typeof操作符,Object.prototype.toString.call()
- typeof操作符以字符串形式,返回未经计算的操作数的类型;检测null的类型时返回的是Object
- 在javaScript中是一切皆对象,因此可利用Object.prototype.toString.call()对象原型的扩展函数更精确的区分数据类型。Object.prototype.toString.call(data)返回值是一个形如"[Object 数据类型]"的字符结果。可通过console.log()观察返回值。
7. 数据类型转换
- 转布尔型:会将任何非空字符串和非零的数值转换为true,其它为flase。转数值型:parseInt()
- toString()、String()、num+""、Number()、parseInt(str)、parseFloat(str)、Boolean()
8. 隐式转换
在某些情况下,Javascript会进行自动类型转换,主要情况有:
- 于检测是否非数值的函数: isNaN(mix)。isNaN()函数,经测试发现,该函数会尝试将参数值用Number()进行转换,如果结果为“非数值”则返回true,否则返回false。
- 递增递减操作符(包括前置和后置)、一元正负符号操作符。这些操作符适用于任何数据类型的值,针对不同类型的值,该操作符遵循以下规则(经过对比发现,其规则与Number()规则基本相同):
(1). 如果是包含有效数字字符的字符串,先将其转换为数字值(转换规则同Number()),在执行加减1的操作,字符串变量变为数值变量。
(2).如果是不包含有效数字字符的字符串,将变量的值设置为NaN,字符串变量变成数值变量。
(3).如果是布尔值false,先将其转换为0再执行加减1的操作,布尔值变量变成数值变量。
(4).如果是布尔值true,先将其转换为1再执行加减1的操作,布尔值变量变成数值变量。
(5).如果是浮点数值,执行加减1的操作。
(6).如果是对象,先调用对象的value0f()方法,然后对该返回值应用前面的规则。如果结果是NaN,则调用toString()方法后再应用前面的规则。对象变量变成数值变量。
- 布尔类型的隐式转换:转换为true:非空字符串、非0数字、true、任何对象;转换成false:空字符串、0、false、null、undefined
变量与常量
- 变量:javaScript中变量通常利用var关键字声明。未赋初始值的变量,默认值会被设定为undefined。可省略var关键字可以直接为变量赋值(不建议使用)。
- 常量:语法:ES6中新增了const关键字,用于实现常量的定义;常量名称总是用大写字母表示。常量在赋值时可以是具体的数据,也可以是表达式的值或变量。常量一旦被赋值就不能被改变。
变量的命名规则和规范
- 命名规则:由字母、数字、下划线、$符号组成,不能以数字开头;不能是关键字和保留关键字(指在javaScript语言中被事先定义好并赋予特殊含义的单词);区分大小写。
- 命名规范:变量名必须有意义;遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。
运算符
运算符就是专门用于告诉程序执行特定运算或逻辑操作的符号。
- 运算符的优先级:()优先级最高 --> 一元运算符(++,--,!) --> 算数运算符(先(*,/,%)后(+,-) --> 关系运算符(>,>=,<,<=) --> 相等运算符(==,!=,==,!==) --> 逻辑运算符(先&&后||) --> 赋值运算符(=,+=,-=, *=,/=,%=)
- 两个“=”表示相等;三个“=”表示全等(不仅类型一样,数值也要一样)。
- JS对于逻辑与运算a&&b,如果a不成立(运算后结果是false,null,'',0,undefined等值)则返回a,如果a成立则返回b。如果每个表达式都成立,则返回最后一个表达式的运算结果,如果有一个不成立,则返回第一个不成立的表达式的运算结果。JS对于逻辑或运算a||b,则是从左边开始,返回第一个的表达式的运算结果,如果全部不成立则返回最后一个表达式的运算结果。&&优先级高于||。
数组
- 数组的定义、获取、遍历、新增例:
<script>
//定义
var arr = ["red","green","blue"];
//获取
console.log(arr[0]);
//遍历
arr.forEach(el => {
//数组遍历
console.log(el);
});
//替换
arr[0] = "yellow";
//新增
arr[3] = "pink";
</script>
- 获取数组长度:length()。
- join()(分隔符):将数组中的元素按指定的符号链接;如果没有分隔符,默认按“,”链接;返回字符串。toString():返回一个字符串,表示指定的数组及其元素。
- 合并字符:concat()把一个数组和另一个数组连接起来。
- 删除数组末尾元素的值:pop()[如果对空数组进行操作,那么返回undefined]。
- 添加数组末尾的值:push()返回的是添加后数组的长度,添加多个值时用“,”分隔开。
- 删除数组第一个元素的值:shift()返回删除的值,如果对空数组进行操作,那么返回undefined。
- 给数组的开始位置添加值:unshift()返回添加值后的数组的长度。
- 替换数组中的元素:splice(startIndex,deletCount,values):startIndex开始处理数据的位置;deletCount删除的数量包含开始位置;values要添加的值,可以省略;返回一个数组,存放删除的元素。
- 截取指定位置数组元素:slice(startIndex,endIndex):startIndex为负数,那么倒数第一位为-1,从右向左数,负几就是倒数第几位开始;endIndex结束位置,如果省略,会截取到元素的最后一位;返回的数组,内容为截取出来的元素。
- sort():对数组的元素进行排序,并返回数组。
- 反序:reverse()反过来输出,颠倒数组中元素的位置。
- split([separator[,limit]]),按条件分割字符串,返回数组。
- indexOf()在父串首次出现的位置,从0开始!没有找到就返回-1。
- lastIndexOf()倒序查找。
- charAt(index)指定索引的字符。
- toLowerCase()转小写。toUpperCase()转大写。
- includes():用于确定数组中是否含有某个元素,含有返回true,否则返回false。
- fill():用一个固定值填充数组中指定下标范围内的全部元素。
- 解构赋值:
//右侧为变量
var arr = [1, 2, 3];[a, b] = arr;
// 输出结果:1-2
console.log(a +'-'+ b);
//变量数值交换
var n1 = 4, n2 = 8;
[n1, n2] = [n2, n1];
// 输出结果:8-4
console.log(n1 +'-'+ n2);
函数
函数是一种数据类型,是js中的一等公民。
匿名函数
//函数表达式中省略函数名
var fn = function (num1, num2) {
return num1 + num2;
};
fn(1, 2);
//自调用方式
(function (num1, num2) {
return num1 + num2;
})(2, 3);
//处理事件
document.body.onclick = function () {
alert('Hi, everybody!');
};
//函数作为返回值
function fn(b) {
var a = 10;
return function () {
alert(a+b);
}
}
fn(15)();
箭头函数
// 设置1个参数
var fn1 = x => x + 2;
console.log(fn1(4));// 输出结果:6
// 设置2个参数
var fn2 = (x, y) => x + y;
console.log(fn2(1, 2) );// 输出结果:3
回调函数
- find():返回数组中满足回调函数的第一个元素的值,否则返回undefined
- every():测试数组的所有元素是否都通过了回调函数的测试
- some():测试数组中的某些元素是否通过由回调函数实现的测试
- forEach():对数组的每个元素执行一次提供的函数
- map():创建一个新数组,其结果是该数组中的每个元素都调用一次提供的回调函数后返回的结果
- reduce():对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值
- reduceRight():接收一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。一个作用域可以访问另外一个函数内部的局部变量。作用:延伸变量的作用域。
递归
如果函数在内部可以调用其本身,那么这个函数就是递归函数。递归函数的作用和循环效果一样。由于递归很容易发生"栈溢出"错误(stack overflow),所以必须要加退出条件return。
对象
面向对象的特征
- 封装性:封装指的是隐藏内部的实现细节,只对外开放操作接口
- 继承性:继承是指一个对象继承另一个对象的成员,从而在不改变另一个对象的前提下进行扩展
- 多态性:多态指的是同一个操作作用不同的对象,会产生不同的执行结果
对象自定义
var o1 = {};
var o2 = {name:'Jim'};
var o3 = {name:'Jim', age: 19, gender:'男'};
var o4 = {
name:'Jim',
age: 19,
gender:'男',
sayHello: function() {
console.log('你好');
}
};
JSON数据格式
{"name":"Tom","age":24,"work":true,"arr":[1,2]}
[{"name":"Tom","age":24},{"name":"Jim","age":25}]
语法:对象.成员
var o5 = {}; //创建一个空对象
o5.name ='Jack'; //为对象增加属性
o5.introduce = function () {
//为对象增加方法
alert('My name is'+ this.name); // 在方法中使用this代表当前对象
};
alert(o5.name); //访问name属性,输出结果:Jack
o5.introduce(); //调用introduce()方法,输出结果:My name is Jack
可变成员语法:对象[变量名]=值
var o6 = {}; //创建一个空对象
var key ='id'; //通过变量保存要操作的属性名
o6[key] = 123; //相当于“o6['id'] = 123”或“o6.id = 123”
JS内置的构造函数
// 通过构造函数创建对象
var obj= new Object(); // 创建Object对象
var str = new String('123'); // 创建String对象
// 查看对象是由哪个构造函数创建的
console.log(obj.constructor); // 输出结果:function Object() { [native code] }
console.log(str.constructor); // 输出结果:function String() { [native code] }
console.log({}.constructor); // 输出结果:function Object() { [native code] }
“对象.constructor”属性指向了该对象的构造函数。通过console.log()输出时,[native code]表示该函数的代码是内置的。
自定义构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHello = function () {
console.log('Hello, my name is'+ this.name);
};
}
使用构造函数
var p1 = new Person('Jack', 18);
var p2 = new Person('Alice', 19);
console.log(p1);
console.log(p2);
p1.sayHello();
console.log(p1.constructor);
私有成员
function Person() {
var name ='Jim';
this.getName = function () {
return name;
};
}
var p = new Person(); // 创建实例对象p
console.log(p.name); // 访问私有成员,输出结果:undefined
p.getName(); // 访问对外开放的成员,输出结果:Jim
函数中的this指向
function method() {
console.log(this.name);
}
// 输出结果:张三
method.apply({name:'张三'});
// 输出结果:李四
method.call({name:'李四'});
function method(a, b) {
console.log(a + b);
}
// 数组方式传参,输出结果:12
method.apply({}, ['1','2']);
// 参数方式传参,输出结果:34
method.call({},'3','4');
Number对象
var num = 12345.6789;
num.toFixed(); // 四舍五入,不包括小数部分,返回结果:12346
num.toFixed(1); // 四舍五入,保留1位小数,返回结果:12345.7
num.toFixed(6); // 用0填充不足的小数位,返回结果:12345.678900
Number.MAX_VALUE; // 获取最大值,返回结果:1.7976931348623157e+308
Number.MIN_VALUE; // 获取最小正值,返回结果:5e-324
Math对象
- PI:获取圆周率
- abs(x):获取x的绝对值,可传入普通数值或是用字符串表示的数值
- max():获取参数中所有参数中的最大值
- min():获取参数中所有参数中的最小值
- random():获取大于或等于0.0且小于1.0的随机值
- Math.random()*(n-m)+m:表示生成大于或等于m且小于n的随机值
BOM
window对象是BOM的顶层(核心)对象。
- confirm()方法
- open()方法,与open()方法功能相反的是close()方法,用于关闭浏览器窗口,调用该方法的对象就是需要关闭的窗口对象。
- setTimeout()和setInterval()方法区别:相同点:都可以在一个固定时间段内执行js程序代码。不同点:setTimeout()只执行一次代码,setInterval()会在指定的时间后,自动重复执行代码。
DOM
元素内容
- 属性属于Element对象,方法属于document对象
- innerHTML在使用时会保持编写的格式以及标签样式
- innerText则是去掉所有格式以及标签的纯文本内容
- textContent属性在去掉标签后会保留文本格式
事件
事件绑定方式
- 行内绑定式:<标签名 事件="事件的处理程序">
- 动态绑定式:DOM元素对象.事件= 事件的处理程序;
- 事件监听式:DOM对象.attachEvent(type, callback);//早起版本的IE浏览器。DOM对象.addEventListener(type, callback, [capture]);//标准浏览器
获取事件对象
var event = e || window.event;
焦点事件
- focus:当获得焦点时触发(不会冒泡)
- blur:当失去焦点时触发(不会冒泡)
正则表达式
- RegExp对象提供的exec()方法:exec()方法用于在目标字符串中搜索匹配,一次仅返回一个匹配结果
- String对象提供的match()方法:match()方法除了可在字符串内检索指定的值外,还可以在目标字符串中根据正则匹配出所有符合要求的内容,匹配成功后将其保存到数组中,匹配失败则返回false
- 定位符:"^",可用于匹配开始的位置;"$",可用于匹配字符串结尾的位置;g表示全局匹配,用于在找到第一个匹配之后仍然继续查找
- 字符类别:大写字母、小写字母和数字可以使用"/w"直接表示。若要匹配0到9之间的数字可以使用"/d"表示。