JavaScript 对网页行为进行编程
JavaScript 先导知识
<script>
// 里面写 js 代码
</script>
JavaScript 变量是存储数据值的容器
// 创建变量的示例
var x = 7;
var y = 8;
var z = x + y;
标识符
标识符是指给变量起的名字,指上面的 x
命名有一些规则
JavaScript 变量能够保存多种数据类型:数值、字符串值、数组、对象等等
变量赋值 | 赋值的类型 | 描述 |
---|---|---|
var lenght = 7; | 数字 | |
var uname = “张三” | 字符串类型 | 数值要用单引或双引 |
var arr = 【“a”,“b”,“c” 】 | 数组 | |
var x = { firstName:‘apple’} | 对象类型 | |
var x ; | undefined | 声明变量未赋值,结果为undefined |
var x = true | 布尔型 | true和false两个值 |
var car = “”; | 字符串类型 | 没有值的意思 |
var car = undefined; | undefined | 任何变量赋值为undefined,类型也为undefined |
var person = null; | 对象类型 | 通过设置值为 null 清空对象 |
var person = undefined; | undefined | 也可以通过设置值为 undefined 清空对象 |
使用 typeof 可以知道某个数据的类型 —— 格式 为 typeof 变量名
var foo = 'bar';
typeof foo //返回的是String
typeof 运算符把对象、数组或 null 返回 object,把函数返回function
typeof {name:'Bill', age:62} // 返回 "object"
typeof [1,2,3,4] // 返回 "object" (并非 "array"在JavaScript中数组即对象)
typeof null // 返回 "object"
typeof function myFunc(){} // 返回 "function"
语法 | 写法 |
---|---|
toString() | 变量 . toString() |
String()强制转换 | String(变量名) |
利用 + 拼接字符串 | var x = 111+ ‘老三’ |
语法 | 写法 |
---|---|
parseInt() | parseInt(变量名) 转为取整数,可以去单位 |
parseFloat() | parseFloat(变量名) 可以去小数 |
Number() | Number(变量名) |
‘数字’可以运算 | 利用运算符- + *隐式转换 |
算数运算符,比较运算符,逻辑运算符,赋值运算符
优先级
运算符 | 优先级从高到低 |
---|---|
() | |
一元运算符 | ++ ,- -, ! |
算数运算符 | + ,- ,* , / , % |
关系运算符 | > , >= , < , <= |
相等运算符 | == , != , === , ! |
逻辑运算符 | && , // |
= | |
, |
功能 | 代码实现 |
---|---|
转义字符 | \n 换行,\t 制表符,\\ 相当于\ |
多行字符 | ``tab键上面的英文符号 |
变量名和字符串输出 | “+”拼接 , 或 __${变量名} |
字符串的长度 | 变量名 . length |
把字符串全大写 | 变量名 . toUpperCase() |
把字符串全小写 | 变量名 . toLowerCase() |
指定字符串出现位置 | str . indexOf( ’ 需要查找的字符 ’ ) |
返回指定文本在字符串中最后一次出现的索引 | str . lastIndexOf( ’ 指定文本 ’ ) |
从位置 50 开始检索,直到字符串的起点 | str . lastIndexOf( ’ 指定文本 ’ ,50 ) |
指定两个索引区间的字符串 | str . substring( _ , _ ) |
返回字符串中指定文本第一次出现的位置 | str . search( ) |
返回字符串中指定下标(位置)的字符串 | str.charAt(下标号); |
将字符串转换为数组 | 字符串 . split(" 什么符号隔开 ") |
删除字符串两端的空白符 | 字符串 . trim() |
只替换首个匹配 | 字符串 . replace(“字符串某个值” , “改变的值”) |
功能 | 代码实现 |
---|---|
返回字符串值,包含了指定位数小数的数字 | 小数值 . toFixed ( 数值 ) |
返回字符串值,它包含了指定长度的数字 | 小数值 . toPrecision( 数值 ) |
以数值返回数值 | 变量 / 文本 / 表达式 . valueOf() |
返回数字,由其参数转换而来 | Number() |
解析其参数并返回浮点数 | parseFloat() |
解析其参数并返回整数 | parseInt() |
数组是一种特殊的变量,它能够一次存放一个以上的值
1. 创建数组
var uname = ["aa","bb","cc"];
var cars = new Array("aa", "bb", "cc");
2. 访问数组元素
// 访问 cars 中的首个元素的值
var name = cars[0];
// 修改 cars 中的首个元素
cars[0] = "Opel";
3. 改变数组元素
// 改变数组的第一个元素
var cars = ["aa", "bb", "cc"];
cars[0] = "AA";
4. 数组的方法
功能 | 代码示例 |
---|---|
把数组转换为数组值(逗号分隔)的字符串 | 数组名称 . toString() |
搜索一个指定元素的位置 | 数组名称 . indexOf(’ 搜索的元素 ') |
截取数组的部分元素 | 数组名称 . slice( _ , _ ) |
在数组结尾添加元素 | 数组名称 . push( " " ) |
删除数组最后一个元素 | 数组名称 . pop() |
在一个数组头部添加元素 | 数组名称 . unshift() |
删除数组头部第一个元素 | 数组名称 . shift() |
按照默认顺序排序 | 数组名称 . sort() |
按照数组顺序反转 | 数组名称 . reverse() |
按索引删除若干元素再添加 | 数组名称 . splice(_ , _ , ‘元素’ , ‘元素’) |
把一个arr和另一个arr结合,返回新的arr | arr . concat([1 , 2 ,3]) |
把每个元素用指定字符连列起来,返回字符串 | 数组名称 . join() |
对象也是变量。但是对象能够包含很多值
// 值按照名称 : 值对的形式编写(名称和值以冒号分隔)
var person = {
firstName:"Bill",
lastName:"Gates",
age:62,
eyeColor:"blue"
};
操作 | 代码示例 |
---|---|
键值(对象中的值定义) | 熟悉名:值 |
访问属性 | 对象名 . 属性名 , 对象名[“属性名”] |
给对象添加属性 | 对象名 . 属性名 = 值 |
删除属性 | delete 对象名 . 属性名 |
检测对象是否有某一属性 | 属性名 in 对象名 |
判断一个属性是否是对象自身的 | 属性名 . hasOwnProperty(" 属性名 ") |
for(var k in 对象名)
console.log(k)——输出的是属性名
console.log(属性名[k])——得到的是属性值
// 用 for ( in )来读取对象的属性和值
var o = {name: 'apple',age: 12}
for (var k in o){
console.log(k); // 输出的是属性名
console.log(o[k]); // 得到的是属性值
}
var d = new Date();
默认情况下,JavaScript 将使用浏览器的时区并将日期显示为全文本字符串
// An highlighted block
var d = new Date();
d的值 Tue Apr 02 2019 09:01:19 GMT+0800 (中国标准时间)
创建Date对象的四种方式
new Date()
new Date(year, month, day, hours, minutes, seconds, milliseconds)
new Date(milliseconds) //从1970 年 1 月 1 日 00:00:00 UTC 到 现在的毫秒数
new Date(date string) // ("October 13, 2014 11:13:00")
第二种方法解读
// 7个数字分别指定年、月、日、小时、分钟、秒和毫秒(0 到 11 计算月份)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);
获取日期的方法
获取为get 设置为 set
方法 | 描述 |
---|---|
getDate() | 以数值返回天(1-31) |
getDay() | 以数值获取周名(0-6) |
getFullYear() | 获取四位的年(yyyy) |
getHours() | 获取小时(0-23) |
getMilliseconds() | 获取毫秒(0-999) |
getMinutes() | 获取分(0-59) |
getMonth() | 获取月(0-11) |
getSeconds() | 获取秒(0-59) |
getTime() | 返回自 1970 年 1 月 1 日以来的毫秒数 |
倒计时的示例
var time = new Date('2020-5-15 21:00:00');
function countDown(time) {
var nowTime = +new Date(); //返回时间总的毫秒数
var inputTime = +new Date(time); //返回的是用户输入时间的毫秒数
var times = (inputTime - nowTime) / 1000; //times是剩余时间总的毫秒数
var d = parseInt(times / 60 / 60);
d = d < 10 ? '0' + d : d;
var m = parseInt(times / 60 % 60);
m = m < 10 ? '0' + m : m;
var s = parseInt(times % 60);
s = s < 10 ? '0' + s : s;
return d + '时' + m + '分' + s + '秒';
}
console.log(countDown(time));
Math 对象允许您对数字执行数学任务
方法 | 描述 |
---|---|
Math.PI; | 圆周率3.141592653589793 |
Math.round(x) | 返回值是 x 四舍五入为最接近的整数 |
Math.pow(x, y) | 返回值是 x 的 y 次幂 |
Math.sqrt(x) | 返回 x 的平方根 |
Math.abs(x) | 返回 x 的绝对(正)值 |
Math.ceil(x) | 返回值是 x 上舍入最接近的整数 |
Math.floor(x) | 返回值是 x 下舍入最接近的整数 |
Math.min(要查的多个数值) 和 Math.max() | 可用于查找参数列表中的最低或最高值 |
Math.random() | 返回介于 0(包括) 与 1(不包括) 之间的随机数 |
功能 | 代码示例 |
---|---|
把数组转换为数组值(逗号分隔)的字符串 | 数组名称 . toString() |
搜索一个指定元素的位置 | 数组名称 . indexOf(’ 搜索的元素 ') |
截取数组的部分元素 | 数组名称 . slice( _ , _ ) |
在数组结尾添加元素 | 数组名称 . push( " " ) |
删除数组最后一个元素 | 数组名称 . pop() |
在一个数组头部添加元素 | 数组名称 . unshift() |
删除数组头部第一个元素 | 数组名称 . shift() |
按照默认顺序排序 | 数组名称 . sort() |
按照数组顺序反转 | 数组名称 . reverse() |
按索引删除若干元素再添加 | 数组名称 . splice(_ , _ , ‘元素’ , ‘元素’) |
把一个arr和另一个arr结合,返回新的arr | arr . concat([1 , 2 ,3]) |
把每个元素用指定字符连列起来,返回字符串 | 数组名称 . join() |
检测结果是否为数组 | arr instanseof Array 结果为boolean, Array.isArray( 测试的数组名) |
JavaScript 函数是通过 function 关键词定义的
// 实例
function myFunction(a, b) {
return a * b;
}
函数中的 arguments 对象
arguments 对象包含函数调用时使用的参数数组
// 函数内部起作用,并且永远指向当前函数的调用者传入的所有参数
function foo(x) {
console.log('x = ' + x); // 10
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
// 即使函数不定义任何参数,还是可以拿到参数的值:
function abs() {
if (arguments.length === 0) {
return 0;
}
var x = arguments[0];
return x >= 0 ? x : -x;
}
abs(); // 0
abs(10); // 10
abs(-9); // 9
// 最常用于判断传入参数的个数
// foo(a, b, c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
if (arguments.length === 2) {
// 实际拿到的参数是a和b,c为undefined
c = b; // 把b赋给c
b = null; // b变为默认值
}
}
函数中 rest 参数
允许接收任意参数
// 在js中允许接收任意个参数,可以用arguments来获取所有参数
function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
1. 变量提升
它会扫描整个函数体的语句,把所有申请的变量提升到函数顶部
自动声明了变量y的值,但是不会提升变量y的赋值
在函数内部首先要用var声明所有变量
2. 全局作用域
不在任何函数内定义的变量就具有全局作用域
默认有一个全局对象window,全局作用域的变量实际上绑定到window属性
(直接访问全局变量 a 和访问 window.a 是一样的)全局变量绑定在window上
3. 名字空间
为了避免在不同文件中使用了相同全局变量造成命名冲突
**解决方案:**把自己的变量和函数全部绑定在一个全局变量中 var My={ }
把自己的代码全部放在唯一的名字空间中
4. 局部作用域
在for循环等语句块中是无法定义具有局部作用域的变量的
'use strict';
function foo() {
for (var i=0; i<100; i++) {
}
i += 100; // 仍然可以引用变量i
}
解决块级作用域,ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量。 【ES6 引入的关键字let】
'use strict';
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
// 在for 外使用i 报错未定义
i += 1;
}
5. 常量
【ES6 引入关键字const】
关键字const来定义常量,
const和let都具有块级作用域,命名大写
6. 解构赋值
把一个数组的元素分别赋值给几个变量
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
可以嵌套:let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
可以忽略:let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
// 借助解构赋值来获取对象的指定属性
var {name, age, passport} = person;
// name, age, passport分别被赋值为对应属性
console.log(name); // 值为对象中的值
var person = {
name: '小明',
address: {
city: 'Beijing'
},
zipcode: {
zip: 'qqq'
}
}
var {name, address: {city, zip}} = person;
name; // '小明'
city; // 'Beijing'
zip; // undefined, 因为属性名是zipcode而不是zip
// 把passport属性赋值给变量id:
var person = {
name: '小明',
person: 'G-12345678'
}
let {name, passport:id} = person;
name; // '小明'
id; // 'G-12345678'
var person = {
name: '小明'
}
// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;
name; // '小明'
single; // true
// 执行之后 person对象中并不会添加single属性
var x,y;
({x, y} = { name: '小明', x: 100, y: 200});
// console.log(name) 结果不会是小明,因为未声明
7. 解构赋值的使用场所
var x=1, y=2;
[x, y] = [y, x];
var {hostname:domain, pathname:path} = location;
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
return new Date(
year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second
);
}
在一个对象中绑定函数,称为这个对象的方法
1. this关键字
JavaScript this 关键词指的是它所属的对象
方法中的this
// this 指的是此方法的“拥有者”,指的是 person 对象,person 对象是 fullName 方法的拥有者
fullName : function() {
return this.firstName + " " + this.lastName;
}
单独的this
// 拥有者是全局对象,因此 this 指的是全局对象,全局对象是 [object Window]
var x = this;
函数中的 this(默认)
// 函数的拥有者默认绑定 this,因此,在函数中,this 指的是全局对象 [object Window]
function myFunction() {
return this;
}
函数中的 this(严格模式)
// ,在严格模式下,this 是未定义的(undefined)
"use strict";
function myFunction() {
return this;
}
事件处理程序中的this
// 在 HTML 事件处理程序中,this 指的是接收此事件的 HTML 元素
<button onclick="this.style.display='none'">
点击来删除我!
</button>
2. that的用法
用that来捕获this
'use strict';
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var that = this; // 在方法内部一开始就捕获this
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - that.birth; // 用that而不是this
}
return getAgeFromBirth();
}
};
xiaoming.age(); // 25
用var that = this;
2. call和apply
apply用法
用apply可以控制this指向
// 方法名.apply(绑定的this变量,[array]) 修复getAge的this指向
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 30
getAge.apply(xiaoming, []); // 30, this指向xiaoming, 参数为空
// 数组值的作用
Math.max.apply(null, [3, 5, 4]); // 5
利用apply()动态的改变函数行为
// 计算代码执行了几回
'use strict';
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};
// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
console.log('count = ' + count); // 3
call的用法
Math.max.call(null, 3, 5, 4); // 5
call和apply的区别
apply()把参数打包成Array再传入;
call()把参数按顺序传入。
Math.max.apply(null,[1,2]);
Math.max.call(null, 3, 5, 4); // 5
函数指向某个变量,既然变量可以指向函数,函数的参数能接收变量
那么一个函数就可以接收另一个函数作为参数
1. map / reduce
map使用
// 用代码实现一个函数 f(x)=x平方
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
reduce
[Array].reduce(对应操作函数) 函数必须接收Array的两个参数
对一个Array求和,就可以用reduce实现:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
[Array].reduce(对应操作函数);
2. filter
用于把Array的某些元素过滤掉,然后返回剩下的元素
筛选
//在一个Array中,删掉偶数,只保留奇数,可以这么写:
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
回调函数
//表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身:
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
console.log(element); // 依次打印'A', 'B', 'C'
console.log(index); // 依次打印0, 1, 2
console.log(self); // self就是变量arr
return true;
});
去除数值中的重复元素
'use strict';
var r, arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
r = arr.filter(function (element, index, self) {
return self.indexOf(element) === index;
});
console.log(r.toString());
3. sort
按数字大小排序,我们可以这么写
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
console.log(arr); // [1, 2, 10, 20]
对于两个元素x和y,
如果认为x < y,则返回-1,如果认为x == y,则返回0,
如果认为x > y,则返回1,
这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。
4. Array其他高阶函数
var arr = ['Apple', 'pear', 'orange'];
console.log(arr.every(function (s) {
return s.length > 0;
})); // true, 因为每个元素都满足s.length>0
console.log(arr.every(function (s) {
return s.toLowerCase() === s;
})); // false, 因为不是每个元素都全部是小写
//找全部是小写或者是大写的元素。
var arr = ['Apple', 'pear', 'orange'];
console.log(arr.find(function (s) {
return s.toLowerCase() === s;
})); // 'pear', 因为pear全部是小写
console.log(arr.find(function (s) {
return s.toUpperCase() === s;
})); // undefined, 因为没有全部是大写的元素
// An highlighted block
var foo = 'bar';
var arr = ['Apple', 'pear', 'orange'];
arr.forEach(console.log); // 依次打印每个元素
有权访问另一个函数作用域中的变量的函数。
如何产生闭包
当一个嵌套的内部(子函数)引用了嵌套的外部(父函数)的变量(函数)时,就产生闭包
闭包的作用
实例用法
function fn1 () {
var a = 2;
var b = '888';
function fn2 () { //执行函数定义就会产生闭包(不用调用内部函数)
console.log(a)
}
}
fn1()
闭包总结
【ES6 标准新增了一种新的函数】(x,y)=>{x*y}
x => x * x
// 上面的箭头函数相当于:第一种
function (x) {
return x * x;
}
// 可以包含多行语句
(x,y) => {
if (x>0){ return x * y; }else {
return x + y ;
}
}
【ES6 标准引入的新的数据类型】
generator 与 普通函数相比有什么用
1.可以在执行过程中多次返回,可以记住执行状态的的函数
2.可以实现用面向对象就可以实现的功能
[巨大好处,把异步回调代码变成‘ 同步 ’代码,在Ajax中可以体会]