1.JS基本语法
1.1 变量
1.1.1 JS语句
弹框警示:alert(“警告”);
提示:prompt(“请输入年龄”,“18”);
控制台打印输出:console.log("");
1.1.2定义变量
- 使用var关键字定义变量
var a
定义变量默认为undefined类型 - `var a = 1 , b = 2 , c = a + b;
- 检测数据类型:
typeof(NaN); typeof(Infinity); typeof(Null);
结果:number number object
null中存放空对象指针也是一个对象
1.1.3 类型检测
- typeof (常用) 检测的数组和null都是Object类型
console.log(typeof(null)) //object
- instanceof 判断是否某种类型,任意类型都是Object的子类
console.log([] instanceof Array) //true
- Object.constructor 原型会被覆盖导致不准确。undefined和null没有constructor属性,使用会报错
const num = 1 console.log(num.constructor === Number); // true
- Object.prototype.toString.call()
console.log(Object.prototype.toString.call([1,2])) //[object Array]
1.1.4 类型转换
- 数据类型转换:.toString() (undefined 和null 用String()方法)
console.log(true.toString());
console.log(String(undefined))
+号两边都是数字为运算,有一边为字符串则拼接为字符串
console.log(true + "")
2. 数值类型
Number()方法;适用任何数据类型
- 纯数字字符串转为对应数字,空字符串和空白字符串转为0,非空非纯数字字符串转为NaN
- 布尔值:true转为1 false转为0
- null转为0
console.log(" ")//0
console.log("undefined")//NaN
console.log("null")//0
console.log("a")//NaN
console.log("123")//123
- parse()方法:
作用:浮点数取整; 字符串转为整数数字(不是数字开头字符串转为NaN) - parseFloat()方法:
作用:转为浮点数; - 应用:
console.log(num);
- Boolean()方法
NaN、0、“”、 空字符串、null、undefined转为false
其余转为true
- 运算
- 逻辑运算:
a&&b a为真则为b
a||b a为真则为a
恒等于 - 比较运算:
隐式转换:“123”-123; true-1 ;flase-0; null-0
undefined-NaN;""-0;“abc”-NaN
null>=(或<=)0 //true
null==0 //flase
undefined == null //true
NaN != NaN //true
Infinity == Infinity //true
Infinity === Infinity //true
“abb” < “baa” //true 只比较第一个字符的ascll码
6 < “12” //true 12转数字和6比较
“6” > “12” //true 比较6和1 的ascll码 - 算术运算(返回一个布尔值)
==只判断值大小是否相等,不判断数据类型
=== 判断数据类型是否相等
- 流程控制语句
break 适用于while for dowhile 语句
break 可以中断循环本层循环,也可中断外层循环;
waiceng:for(i=0;i>10;i++){
for(j=0; j>8, j++){
console.log(i,j);
if (j>=2){
break waiceng ;
}
}
}
2函数
浏览器在调用函数的时候会开辟新的空间执行函数内容。局部变量退出作用域时会销毁。全局变量在关闭浏览器时销毁。
- 作用域:函数首先会调用自己内部变量,未找到时会调用全局变量。产生遮蔽效应。定义变量时不加var关键字则定义全局变量
- return:将返回值作为函数的结果。没有return则为undefinde
sum(a,b) {
return a+b
}
-
arguments对象
argument对象中存储传递的所有实参,是一个伪数组,可以遍历。函数实参和形参个数不一致,所有实参都会存储在函数内部的arguments数组对象中。可以利用argumens中数组长度实现java中的重载。 -
预解析:执行代码时分为预解析和代码执行过程。
1.把变量声明提升到当前作用域的最前面,只提升声明不赋值
2.把函数声明提升到当前作用域的最前面,只提升声明不调用
3.先提升var的创建和初始化赋值不会被提升,let的创建被提升,初始化和赋值不会被提升,函数的创建\初始化\赋值都会被提升
4.函数表达式进行的是变量声明提升。提升后变量内部存的是undefined。
5.IIFE自调用函数。定义时就立即使用。通过添加±()!实现矮化成表达式后面加()可以立即执行
var foo=function () {
console.log(2);
}();//函数表达式方式可以在定义时被立即执行
function fun(){
console.log(1);
}();
或 (function fun(){
console.log(1);
})();
//常用:
(function (a){
console.log(a);
})(4);
- 异常
throw new Error(“抛出异常提示”);
高阶函数
屏蔽实现细节,抽象通用问题
函数作为参数
function fliter(arr,fn){
let result = []
for(let i=0 ;i<arr.length;i++){
if(fn(arr[i])){
result.push(arr[i])
}
}
}
let array = [1,2,3,5,6]
let r = fliter(array,function(item){
return item%2 === 0
})
console.log(r)// 2,6
函数作为返回值
function once(fn){
let done = false
return function(){
if(!done){
done = true
return fn.apply(this,arguments)
}
}
}
let pay = once(function(money){
console.log(`支付${money}RMB`)
})
pay(6)
pay(6)
//调用两次函数只执行一次
作用域链
function bar() {
console.log(myName)
}
function foo() {
var myName = "极客邦"
bar()
}
var myName = "极客时间"
foo() //输出结果为极客时间
在每个执行上下文的变量环境中都有一个outer指向外部执行上下文。如果代码使用到一个变量,js引擎会在当前执行上下文中寻找,如果没有就在outer指向的执行上下文中查找. bar()函数的outer指向(作用域链指向)是由词法作用域决定的。foo和bar的上级作用域都是全局作用域,词法作用域在编译阶段就决定好了,与函数调用无关
4.1词法作用域
概念:是由代码中函数声明的位置来决定,是静态的作用域,通过它能够预测代码在执行过程中如何查找标识符
词法作用域由代码中函数声明的位置决定,在编译阶段已经确定,与函数调用无关。
块级作用域中的变量查询
function bar() {
var myName = "极客世界"
let test1 = 100
if (1) {
let myName = "Chrome浏览器"
console.log(test)
}
}
function foo() {
var myName = "极客邦"
let test = 2
{
let test = 3
bar()
}
}
var myName = "极客时间"
let myAge = 10
let test = 1
foo()
5.闭包
函数定义时能记住自己生成的作用域环境和函数自己。
定义:根据词法作用域的规则,内部函数总是可以访问外部函数声明的变量,当通过通过一个外部函数返回一个内部函数后,即使该外部函数已经执行结束,内部函数引用外部函数都买的依然保存在内存中,这些变量的集合称为闭包
用途:1.可以在函数外部读取函数内部成员 2. 让函数内成员始终存活在内存中
使用自调用函数解决闭包作用域限制的问题
function foo() {
var myName = "极客时间"
let test1 = 1
const test2 = 2
var innerBar = {
getName:function(){
console.log(test1)
return myName },
setName:function(newName){ myName = newName }
}
return innerBar
}
var bar = foo()
bar.setName("极客邦")
bar.getName()
console.log(bar.getName())
执行到foo函数内部的return innerBar的时候
内部函数getName和setName总是可以访问他们外部函数
foo中的变量,所以当iinnerBar对象返回给全局变量bar时,虽然foo函数执行结束,但是getName和setName依然可以使用函数中的变量myName和test1的
foo函数执行完成以后它执行的上下文从栈中弹出,由于函数方法中使用了foo函数内部变量所以这两个变量依然保存在内存中。
当函数变量被调用时,沿着当前执行上下文——》foo函数闭包——》全局执行上下文的顺序查找变量。
闭包回收
如果闭包函数是一个全局变量,闭包会一直存在知道页面关闭;如果闭包以后不再使用,就会造成内存泄漏
如果引用闭包的函数是个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么 JavaScript 引擎的垃圾回收器就会回收这块内存。
所以在使用闭包的时候,你要尽量注意一个原则:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。
3.对象
学习文档:MDN
- 创建对象:
- 方法一:通过字面量创建对象
var person = {
name : "zs",
age : "19",
sayHi : function {
console.log("nihao");
}
}
- 方法二:使用new Object创建
var person1 =new Object();
//添加属性方法
person1.name = "ZS";
person1.sayHi = function () {
console.log("hellow");
};
new 在内存中创建了新的空对象;让this指向新的对象;执行构造函数为新对象加属性和方法;new会返回这个新对象。new一个构造函数就会创建一个新对象
- 方法三:使用工厂方法创建对象
function createPerson(name,age) {
//创建一个空对象
var person = new Object();
//添加属性和方法
person.name = name;
person.age = age;
person.sayHi = function (){
console.log("hello");
};
//将对象作为函数返回值
return person;
}
//想创建对象可以调用工厂函数
var p1 = createPerson("zs","18");
console.log(p1);
- 方法四:自定义构造函数
function Person(name,age){// 构造函数首字母大写
//不需要使用 new 一个新对象,用this替代将来创建的新对象
this.name = name;
this.age = age;
this.sayHi = function () {
console.log("hello");
};
//new 创建新对象会自动生产返回值。不需要添加return
var p1 = new Person("zs",18);
console.log(p1);
}
- 调用:
- 方法一
console.log(person.name);
person.satHi();
- 方法二
console.log(person["name"]);
person["sayHi"]();
对象内部调用时用this关键字
delete person.name;//删除属性
person.age=10;//修改或新增属性
- 对象遍历
for in 循环
for(var k in person){
console.log(k+"项的属性值为"+person[k]);
}
- 内置对象
- Math对象
Math.pi 圆周率
Math.random() 生产随机数
Math.floor()/Math.ceil() 向下/上取整
Math.abs() 绝对值
Math.max()/Math.min() 最大/小值
Math.sin()/Math.cos() 正弦函数
Math.power/Math.sqrt() 指数幂/平方根
- 创建数组对象的两种方式
- 字面量方式
var arr = [1,2,3];
- new Array() 构造函数方法
var arr1 = new Array();//空数组
var arr2 = new Array(1,2,3) //可以传参
var arr3 = new Array("zs","li","ww");//字符串数组
console.log(arr instanceof Array) //true;
console.log(arr1 instanceof Array) //true;
- 数组对象数组属性和方法
-
Array 对象
instanceof 检测某个实例是否时某个对象类型
toString() 把数组转化成字符串,逗号分隔每项
push() 数组末尾添加元素,并返回操作后长度
pop() 删除数组最后一项,返回删除项
shift() 删除数组第一项,返回删除项
unshift() 在数组开头添加一个或多个元素,返回操作后长度 -
concat() 两个数组合并成为一个新的数组,原数组不受影响
var arr = [1,2,3] , ar = [4,4];
var arr1 = arr.concat([5,4,3]);
var arr2 = arr.concat(ar);
console.log(arr);//[1,2,3]
console.log(arr1);//[1,2,3,5,4,3]
console.log(arr2);//[1,2,3,4,4]
- slice(start,end) 从当前数组中截取一个新的数组,不影响原来数组,返回一个新数组,从start到end(不含)的元素;参数为正表示下标,为负表示从后往前数几个。不传值时表示浅拷贝一份
var arr = [1,2,3,4,5,6];
var arr1 = arr.slice(2,4); //[3,4]
var arr2 = arr.slice(-4,-1); //[3,4,5]
var arr3 = arr.slice(-1,-4); //[]
var arr2 = arr.slice(-4) //[3,4,5,6] 一直截取到结束
- splice(index,howmany, element1···) 删除、插入、替换
index: 删除元素开始位置
howmany: 删除元素个数,可以是0
elememt1 :要替换的新数据;
var arr = [1,2,3,4,5,6,7,8];
arr.splice(2,5); //删除
console.log(arr.splice(2,5));//[3,4,5,6,7]返回删除的数组
console.log(arr); //[1,2,8] 从下标2开始删5个
var arr1 = [1,2,3,4,5,6,7,8];
arr1.splice(2,5,"h1","h2"); //替换
console.log(arr);//[1,2,3,h1,h2];
var arr2 = [1,2,3,4,5,6,7,8];
arr2.splice(3,0,"h1","h2"); //增加
console.log(arr2);//[1,2,3,h1,h2,4,5,6,7,8]
- indexOf() 查找数组中首次出现元素的下标
var arr = [1,2,3,4,5,6,7,4,5];
console.log(arr.indexOf(4)); // 3
console.log(arr.lastIndexOf(4)); // 7
console.log(arr.index(8)); //-1
-
reverse() 数组完全颠倒 返回值为倒叙后值
arr.reverse();
-
sotr() 默认根据字符编码顺序,从大到小
var arr = [1,2,3,4,5,10,20];
arr.sort(function(a,b){ //实现正序
if(a < b ) {
return -1; //表示a 排在 b 前面
}else if (a > b>) {
return 1; //表示 a排在 b后面
}else {
return 0; //a 和 b不变
}
});
console.log(arr);
- join() 通过参数作为连字符将数组的每项用连字符连城完整的字符串
var str = arr.join();
console.log(str); //1,2,3,4,5,6
var str1 = arr.join(*);
console.log(str1); //1*2*3*4*5*6
- 基本包装类型:基本类型数据进行特殊操作时,会暂时包装成对象,结束后销毁。
var str1 = "abcde" ;
var str2 = new String("abcdef") ;
- 字符串特点
字符串不可修改,更改字符串内容只是整改存放字符串内容的地址。字符串的所有方法,都不可修改字符串本身。
- str.length
- str.charAt() 返回指定位置的字符,从0 开始
- str.indexOf() 返回指定的字符串中第一个出现位置的下标
- str.concat() 连接两个或多个字符串,生成新串,原串不变
var str2 = str.concat("hahaha","h2")
- str.split() 把一个字符串分割成字符串数组
var arr = str.split("");
- toLowCase()/toUpperCase() 字符串转小写/大写
- slice(start, end) 提取字符串某个部分,返回提取部分
- substr(start,howmany) 抽取从start下标开始howmany长度的自字符
- substring(start, end) 提取介于两个指定下标之间的字符,原串不变,返回提取值
[folktail官网][https://folktale.origamitower.com/]