JS基础
JS用处
JS组成: ECMAScript(JavaScript语法)、DOM(文档对象模型)、BOM(浏览器对象模型)
JS书写
有3种不同的书写位置
<!-- 外部 -->
<script src="m.js">
// 内嵌式的js
alert('1254')
</script>
<!-- 行内式的js,直接写到元素内部 -->
<input type="button" value="1" onclick="alert('222')">
网页输入框:prompt(’…’)
弹出警示框,输出给用户看:alert(’…’)
变量
就是一个装数据和盒子,本质就是内存中存放数据的空间。
声明变量
var …;声明变量,给变量分名字。
赋值与初始化与c相似。变量会被覆盖。
‘=’前后均要加空格
imply global暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局变量。
命名规范
数据类型
分为两类:简单数据类型(Number,String,Boolean,Undefined,Null)和复杂数据类型(object)。
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整型值和浮点型值 | 0 |
String | 字符串型 | “” |
Boolean | 布尔值型 | false |
Undefined | var a;声明了变量a但是没有赋值,此时a = undefined | undefined |
Null | var a = null;声明了变量a为空值 | null |
Number数字型
进制
// 1.在JS中八进制前面加0,十六进制前面加 0x
var num1 = 07; // 对应十进制的7
// 2.十六进制数字序列范围:0~9以及A~F
var num = 0xA;
「数字型范围」JavaScript中的数值有最大值和最小值
最大值:Number.MAX_VALUE,值为:1.7976931348623157e+308
最小值:Number.MIN_VALUE,值为:5e-32
特殊值:Infinity 无穷大 -Infinity 无穷小
NaN 代表一个非数字,如果输入结果不是数字时使用
isNaN():用来判断一个变量是否为非数字的类型,返回ture和false。非数字型为true,数字型为false。
String字符串型
用单引号包含字符串,转义字符与c相似
字符串拼接用+,字符串和其他类型拼接,都会是字符串,数字型相加还是数字型。
alert(‘hello’+’ ‘+’ world’);//hello world
alert(‘100’+’ '+‘100’);//100100
alert(100+100);//200
还可以加一个变量。
console.log(‘今年’+age+‘岁’);
Boolean布尔型
和数字型相加时,也变数字型。
获取变量类型及转换
typeof检测变量的数据类型。
var num = 10;
console.log(typeof num)//结果为 number
转换为字符串
null会转化为数字0,undefined会转化为NaN,true为1,false为0
//1.把数字型转为字符型 变量.toString()
var num = 10;
var str = num.toString();
//2. 利用String() 必须大写
console.log(String(num));
//3.+拼接字符串 隐式转换
console.log(num+'');
转换为数字型
//1.parsenInt() 得到整数,直接取整,不进位
parseInt(age);
parseInt('rem120px');//NaN,逐位读取
//2.parsenFloat() 得到浮点数,如果是整数就没有小数
parseInt(age);
//3.利用Number(变量)
Number(str);
//4.利用-*/算术运算,隐式转换
console.log('12'-0);
console.log('123'-'120');
做一个简易计算机👇
var num1 = prompt('请输入第一个数');
// alert('你的年龄是'+age+'岁');
var num2 = prompt('请输入第二个数');
var num = parseInt(num1) + parseInt(num2) ;
alert('总数是'+num);
循环操作与c无太多差别,不做一一赘述。
但是需要注意,switch有不同的地方,swtich(n)中的n可以取字符等,还有可以耦合。
var n;
switch(n){
case "Monday":
case "Tuesday":
case "Wednesday":
console.log("workingday");
break;
case "Sunday":
console.log(restingday);
break;
}
函数
与c也差不多,但是函数声明用function。
function saiHi(){
console.log('hi');
}
//调用函数
sayHi();
形参与参数数量不匹配时,映射规则👇
function getSum(a, b, c) {
return a + b + c;
}
// js中形参的默认值是undefined。
// 调用函数
var n = getSum(1, 2);// n = NaN
var n = getSum(1, 2, 3, 4); //1 + 2 +3 = 6
不确定有多少参数传递时,可以用arguments,存储了传递的所有实参。
function fn(){
console.log(arguments);
//这时arguments就是参数数量,是一个伪数组形式。
}
fn(1,2,3);
伪数组并不是真正意义上的数组。
- 具有数组的length
- 按照索引的方式进行存储
- 没有真正数组的一些方法。
函数封装就是将功能在函数内完善,输入输出都在函数内完成,函数本身就是一种封装。
作用域
作用域链:内部函数访问外部函数的变量,采取链式查找的方式来决定取值。链式查找为就近原则。
预解析
js引擎会把js里面所有的var 还有function提升到作用域的最前面,即为变量提升和函数提升先预解析再代码执行。
console.log(num);//坑1
var num = 10;
//输出undefined,因为预解析变量声明前提,但赋值不前提。
// 即为以下效果👇
var num;
console.log(num);
num = 10;
fun();//报错,坑2
var fun = function(){
}
//还是因为预解析,如下
var fun;
fun();
fun = function() {
}
// 特殊案例1
var num =10;
fun();
function fun() {
console.log(num);
num = 20;
}
//输出结果会是undefined,函数内部先预解析num,此时num并没有值
// 特殊案例2
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
//结果为 9 9 9 9 9 报错
//分析:先执行函数, var a = b = c = 9;等价于var a = 9;b = 9;c = 9;bc属于暗示全局变量,未声明赋值为全局变量。
对象
对象一组无需的相关属性和方法的集合,类似与结构体,但是是无序的且有不同属性。
创建对象
- 用对象字面量
var obj{
name:'',
age:'',
sayHi:function(){
...
}
}
//里面的属性或方法采取键值对的形式 键 属性名 : 值 属性值
//调用与结构体一样,对象名.属性或对项目【‘属性名’】
一次创建一个对象,里面很多属性和方法是大量相同的,所以创建多个对象时,可以用函数的方法。
//构造函数,形参为传入的值,在函数中传给对象的属性
function creat(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.game = function(ball){
console.log(ball)
};
}
var James = new creat('james',30,'man');
var lebron = new creat('lebron',31,'man');
console.log(James.name);
James.game('basketball');
new关键字执行过程
- 在内存中创建了一个空的对象
- this就会指向刚才擦黄建的空对象
- 执行构造函数里卖弄的代码,给空对象添加属性和方法
- 返回这个对象
遍历对象
用for in for(变量in对象)
对象接上
for(var k in James){
console.log(k); //得到属性名
console.log(James[k]); //得到属性值
}
//变量一般用k
内置对象
JS自带的一些对象,可直接使用。如:Math,Date,Array,String等
Math对象
不是一个构造函数,不需要new调用,直接使用就可。
随机数方法 Math.random()返回一个随机小数。
// 得到两个数之间的随机数
function getRandom( min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1,10));
// 模拟随机点名
var arr = ['san','si','wu','liu'];
console.log(arr[getRandom(0,arr.length - 1)]);
Date 日期对象
为构造函数,需要new去创建。若没有参数,则为当前系统时间。
参数常用写法:
- 数字型 2021,03,25
- 字符串型 ‘2021-03-25 8:8:8’ 需要用单引号
// 格式化日期
var date = new Date();
console.log(date.getFullYear());//返回当前年份
console.log(date.getMonth() + 1);//返回当前月份,但是是从0开始到11,所以要+1
console.log(date.getDate());//返回几号
console.log(date.getDay());//返回星期几,但是是阿拉伯数字,可以配合数组,来转换成汉字
console.log(date.getHours());//返回当前小时
console.log(date.getMinutes());//返回当前分钟
console.log(date.getSeconds());//返回当前秒数
//返回秒数如果想要两位数,可判断是否小于10,是则加‘0’
console.log(Date.now());//获取当前距离1970.1.1总的毫秒数,也称时间戳,永不重复
//获取当前日期
var year = date.getFullYear();
var month = date.getMonth() + 1;
var date = date.getDate();
var day = date.getDay();
var arr = ["日", "一", "二", "三", "四", "五", "六"];
console.log(
"今天是" + year + '年'+ month + '月' + date + '日' + '星期' + arr[day]
);
这个时候,浏览器并不会出现答案,而是报错
这时候,回头发现,是对象和定义的变量名冲突了。
所以,一定要注意对象和变量名,虽然可以随便起,但也不要重复。
倒计时
用时间戳做
function countDown(time){
var nowTime = +new Date();
var inputTime = +new Date(time);
var times = (inputTime - nowTime) / 1000;//倒计时的总秒数 h
var d = parseInt(times / 60 /60/24);//天
d = d < 10? '0' + d : d;
var h = parseInt(times / 60 /60%24);//时
h = h < 10? '0' + h : h;
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 + '天' + h + '小时' + m + '分' + s + '秒'
}
alert('还剩下' + countDown('2021-3-26 17:38:00'))
数组对象Array
「创建数组的两种方式」
- 字面量方式var arr = [1,“test”,true];
- 实例化数组对象 new Array()var arr = new Array();
- 注意:上面代码中arr创建出的是一个空数组,如果需要使用构造函数Array创建非空数组,可以在创建数组时传入参数
- 如果只传入一个参数(数字),则参数规定了数组的长度。
- 如果传入了多个参数,则参数称为数组的元素。
检测是否为数组
instanceof,Array.isArray
var arr = [];
var obj = {};
console.log(arr instanceof Array);//true
console.log(obj instanceof Array);//false
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));//优先级更高
增删数组元素
不跟参数则增删一个,参数即为增加或删除的元素。
案例:有一个数组{15,12,20,21,18},把超过20的删掉,剩余添加到一个新数组中去。
(其实就是将元素增加到新数组中去,这时可以用push,很方便)
//核心:
var arr = [15,20,12,21,18];
var newArr = [];
for(var i = 0;i<arr.length;i++)
{
if(arr[i]<20)
newArr.push(arr[i]);
}
反转arr数组: arr.reverse();
数组排序
arr.sort,此时只能排个位数,若双位数则比较最高位就停止,2比13大。所以有改进写法。
- 如果传入“function(a,b){ return a-b;}”,则为升序
- 如果传入“function(a,b){ return b-a;}”,则为降序
返回数组元素的序号
var arr = [1, 2, 3, 4, 5, 4, 1, 2];
// 查找元素2的索引,
console.log(arr.indexOf(2)); // 1
//返回第一个满足条件的索引号
// 查找元素1在数组中的最后一个索引
console.log(arr.lastIndexOf(1)); // 6
//找不到元素,返回-1
案例:
//封装一个去重的函数
function unique(arr){
var newArr[];
for(var i = 0;i<arr.length;i++)
{
if(newArr.indexOf(arr[i])===-1)
newArr.push(arr[i]);
}
}
===:三个等号我们称为等同符,当等号两边的值为相同类型的时候,直接比较等号两边的值,值相同则返回true,若等号两边的值类型不同时直接返回false。
例:100===“100” //返回false
abc===“abc” //返回false
‘abc’===“abc” //返回true
NaN===NaN //返回false
false===false //返回true
数组转换为字符串
join方法如果不传入参数,则按照 “ , ”拼接元素
var arr = [1, 2, 3, 4];
var arr2 = arr;
var str = arr.toString(); // 将数组转换为字符串
console.log(str); // 1,2,3,4
var str2 = arr2.join("|");//按照键入字符将数组转换为字符串
console.log(str2);
字符串对象
基本包装类型
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。
// 下面代码有什么问题?
var str = 'andy';
console.log(str.length); // 4
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为 js 会把基本数据类型包装为复杂数据类型,其执行过程如下 :
// 1. 生成临时变量,把简单类型包装为复杂数据类型
var temp = new String('andy');
// 2. 赋值给我们声明的字符变量
str = temp;
// 3. 销毁临时变量
temp = null;
字符串的不可变
其实就是字符串占内存,不会自动销毁,不建议过多拼接字符串。
- 指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
- 当重新给字符串变量赋值的时候,变量之前保存的字符串不会被修改,依然在内存中重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变。
- 由于字符串的不可变,在**「大量拼接字符串」**的时候会有效率问题
根据字符返回位置
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是返回指定字符的位置的方法:
// 根据位置返回字符
// 1. charAt(index) 根据位置返回字符
var str = 'andy';
console.log(str.charAt(3)); // y
// 遍历所有的字符
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i));
} // a n d y
// 2. charCodeAt(index)
//返回相应索引号的字符ASCII值 目的: 判断用户按下了那个键
console.log(str.charCodeAt(0)); // 97
// 3. str[index] H5 新增的
console.log(str[0]); // a
案例:查找字符串中指定字符的位置和次数
var str = 'asdfghjkloifuytrewfsdfghjklhgv';
var index = str.indexOf('f');//找到第一个f的位置
var num = 0;//计数器
while(index !=-1){
console.log(index);//输出已找到的位置
num++;
index = str.indexOf('f',index + 1);//从找到的下一个开始找
}
console.log('o出现的次数为' + num);
案例2:输出每个字符出现的个数,并输出最多的字符
var str = 'asdfghjkloifuytrewfsdfghjklhgv';
var o = [];//对象记录每个字符个数
for(var i = 0;i<str.length;i++)
{
var chars = str[i]; // 每个字符单独提取出来
if(o[chars]) // 如果该字符在o中已有,则自增
{
o[chars]++;
}
else o[chars] = 1; // 如果没有,则为第一个
}
//补充:用o[chars]而不用o。chars是因为字符串本身带单引号,o[chars]可以直接得到属性值
console.log(o);
//得到出现最多的字符
var max = 0;
var ch = '';
for(var k in o)
{
if(o[k]>max)
{
max = o[k];
ch = k;
// k 得到是 属性名
// o[k] 得到的是属性值
}
}
console.log("最多的字符是" + ch);
字符串操作类型
有比较多方法,使用可查阅
var str = 'nb';
console.log(str.concat('jc'));//拼接,nbjc
console.log(str.substr(1,1));//截取 substr('截取的起始位置', '截取几个字符');
console.log(str.replace('b','bbbb!')); //替换 replace('被替换的字符', '替换为的字符')
var str3 = "red&pink&blue";
console.log(str3.split("&")); // [red,pink,blue]
//split 分割字符,按输入的字符为切割点
简单类型与复杂类型
简单类型有较基本数据类型或值类型,复杂类型又叫引用类型。
-
**「简单类型(基本数据类型、值类型)」:**在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null
null默认返回值为object,为空对象。如果有变量打算存储对象,暂时没想好放什么,就放null -
**「复杂数据类型(引用类型)」:**在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;
简单数据类型的存储方式
值类型变量的数据直接存放在变量(栈空间)中
复杂数据类型的存储方式
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
如果,栈中有同样的地址指向堆中的数据,则通过其中一个栈修改堆,另一个也会受影响,不考虑作用域。
下面这个案例可以更好理解👇
function Person(name) {
this.name = name;
}
function f1(x) { // x = p
console.log(x.name); // 2. 这个输出刘德华
x.name = "张学友";
console.log(x.name); // 3. 这个输出张学友
}
var p = new Person("刘德华");
console.log(p.name); // 1. 这个输出刘德华
f1(p); //f1中已经通过x=p,构成两栈一堆,修改堆,栈也会被修改
console.log(p.name); // 4. 这个输出张学友
至此,JS基础入门知识已全部结束,还有JS进阶,那个才是真正与界面有关