一、JS输入输出语句
prompt(’’):输入框 取回的值为字符型
alert(’’):弹出提示框
console.log(’’)控制台输出
二、变量
1.变量的初始化
var myname = 'shy' console.log(myname);
2.变量的使用
var myname = 'shy'
var address = 'slqd'
var age = 18
var email = 'sssqq.com'
var gz = 2000;
然后一一console.log输出
3.案例:
(1).输入用户姓名 存储到一个myname的变量中
var myname = prompt('请输入您的名字');
(2).输出用户名
alert(myname);
4.变量的语法扩展
(1).更新变量 变量被重新赋值后,原有的值会被覆盖,后浪推前浪
(2).同时声明多个变量
var age = 18, address = 'sss',gz = 2000;
(3).声明变量的特殊情况
a.只声明不赋值输出结果是undefined
var sex;
console.log(sex)
b.输出一个不存在的变量,不声明不赋值直接使用,会报错
console.log(sfs);
c.不声明直接赋值使用
qq = 123;
console.log(qq);
(4).最好,声明变量时赋值
5.交换两个变量的值
js编程有很强的逻辑性,值的交换需要一个临时变量
6.js是一种弱类型,或者说是动态语言,变量的数据类型只有在程序运行中会被自动确定,根据等号右边的值来去确定。js是动态语言,变量的数据类型是可以变化的。
三、简单数据类型
1.Nunber 数字型,包含整型值,和浮点型值 默认值为0
(1).进制:
1.八进制 0~7 在程序中在数字前加0 表示八进制
var num1 = 010;//8
2.十六进制 0~9 a~f 数字前加0x表示十六进制
var num2 = 0xa;//十六进制的10
(2).数字范围:Number.MAX_VALUE,MIN_VALUE
(3).三个特殊值:
Number_MAX_VALUE*2//Infinity 无穷大,大于任何值;
-Number_MAX_VALUE//-Infinity,相反。
NaN,代表一个非数值 比如:string - int ,结果是NaN
isNaN()这个方法判断非字,并返回一个值,如果是数字返回false,不是数字返回true,用途, 可验证表单中用户输入是否为数字。
2.Boolean 布尔型,true和false,等价1和0 默认值为false true与false是参与加法运算的
3.String 字符串类型,“zzz” ,默认值为,“”,可以是 ’ ’ / " "
js中更推荐使用单引号 嵌套使用:外单内双,反之
字符串转义符:都是用\开头,\n换行,\斜杠,‘单引号,’'双引号,\tTab缩进,\b空格b=blank
字符串长度:检测获取字符串长度 length
var str = 'my name is andy';
console.log(str.length);
字符串的拼接:字符串 + 任何类型=新字符串
console.log('1'+'2');
字符串拼接加强:变量不要写到字符串中,是通过和字符串相连的方式实现的
4.Undefined
var a;
声明了变量没有给值,a = undefined 默认值为undefined
5.Null 空值 默认值为null
四、获取变量的数据类型
typeof 用法:
var num = 10;
console.log(typeof num);
五、数据类型转换
1.转换为字符串:
(1).toString()
var num = 10;
var str = num.toString();
(2).String()强制转换
console.log(String(num))
(3).加号拼接字符串 ,常用,隐式转换,把其他数据类型放入也可以转
console.log(num+'');
2.转换为数字型:
(1).parseInt(string) string转换整数 得到的是整数,
var age = prompt('请输入');
console.log(parseInt(age));
小数只取整数部分,小数部分完全去掉,不会进位如果加上px,会被去掉:
console.log(parseInt('120px'))
console.log(parseInt('rem120px'));//得到结果是NaN,这两种情况下面Float相同
(2).parseFloat(string) string转换浮点数值,
console.log(parseFloat('3.14'));
(3).Number()强制转换函数 将string类型转换为数值型,
console.log(Number(10))
(4).js隐式转换,- * /,
console.log('123'-0);//int
console.log('123'-'120');//int,结果为3
console.log('123'*1);//int
3.转换为布尔型:Boolean()函数,
console.log(Boolean(''));//false
console.log(Boolean(0));//false
console.log(Boolean(NaN));//false
console.log(Boolean(null));//false
console.log (Boolean(undefined));//false
除了这五个,其余都转为true
六、运算符+,-,*,/,%
注意:不要直接判断两个浮点数是否相等, 浮点数在计算时精度远远不如整数
1.表达式和返回值:赋值
2.递增和递减必须配合变量使用
后置自增:表达式先返回原值,后面再自增1,
a++ = 10 a = 11;++a = 11;
3.比较运算符
= 赋值,把右边给左边
==判断,判断两边值是否相等,此时有隐式转换,
18 == '18' //结果为true
===全等,判断两边的值是否完全相同,
18 === '18' //结果为false
4.逻辑运算符,逻辑与&&,逻辑或||,逻辑非!
5.!短路运算:当左边表达式的值确定结果时,就不再继续运算右边表达式的值,面试考题请注意!
(1).逻辑与短路运算,如果表达式1结果为真,则返回表达式2 123 && 456 //返回456, 如果表达式 为假,则返回表达式1。
0 && 456;//返回0
如果有空的或者否定的为假,其余为真&&
123 &&1+2//返回空null
(2).逻辑或短路运算,如果表达式1结果为真,则返回表达式1,为假,则返回表达式2,
123 || 456//返回123
0 || 456 //返回456,
var num = 0;
console.log(123 || num++);
console.log(num);//返回0
逻辑中断很重要,它会影响我们程序的运行结果。左边表达式的真假会影响右边表达式到底要不要执行,对结果会有很大的影响。
6.运算符优先级:
(1).小括号()
(2).一元运算符 ++ – !
(3).算术运算符 先* / %后+
(4).关系运算符 > >= < <=
(5).相等运算符 == != === !==
(6).逻辑运算符 先&& 后||
(7).赋值运算符 =
(8).逗号运算符 ,
七、流程控制
1.顺序流程控制
2.分支流程控制
3.分支流控制if语句
4.三元表达式
5.分支流控制switch语句,注意事项:
(1).在开发时,表达式经常写成变量
(2).我们num的值和case里面的值相匹配的时候是全等 num === 1
(3).如果当前case里面没有break,则不会退出switch,会继续执行下一个case
6.switch和if elseif区别:
(1).一般情况下,可以相互替换
(2).switch语句通常处理固定值,if elseif比较灵活,常用于范围判断
(3).switch语句进行条件判断后直接执行到程序的条件语句,效率更高,而if elseif 需要从上往下依 次判断,效率低一些。
(4).当分支少时,用if elseif效率高
(5).分支多时用switch
八、循环
for(初始化变量;条件表达式;操作表达式){//循环体}
初始化变量 就是用var 声明的一个普通变量,通常用作计数器
条件表达式,就是用来决定每次循环是否继续执行,就是终止条件
操作表达式,是每次循环最后执行的代码,常用于计数器进行更新
(1).首先执行里面的计数器变量, var i = 1;但是这句话在for里面只执行一次 i(index)
(2).i <= 100 来判断是否满足条件 就去执行循环体 ,不满足条件退出循环
(3).最后执行i++,这是单独写的代码递增,第一轮结束
断点调试:sources,打断点,刷新
双重for循环:外面循环执行一次,里面循环执行全部
小结:
(1).可以重复执行某些相同代码
(2).可以重复执行某些操作,比如算术运算符加法操作
(3).双重for循环可以做更好看的效果
(4).双重for循环,外面执行一次,里面执行全部
(5).分析比写代码更重要
(6).核心算法
2.while
3.do…while:先执行代码块,在进行判断
4.小结:while,和do…while 可以做更复杂的判断条件
5.continue 关键字,退出本次循环,继续执行剩余次数循环
6.break:退出整个循环
九、数组
1.创建数组的方法:
var arr = new Array();var arr2 = [];
数组中元素用’,'隔开,可放任意类型的数据,加入数据的操作称为数组的初始化。
2.索引:索引(下标)从零开始,用来访问数组中的元素 ,数组名[索引号]
3.遍历数组:从头到尾访问,遍历时用for循环,i必须从零开始,因为索引是从零开始的。
4.数组长度:数组名.length
(1).数组的长度是元素的个数,不要跟索引号
(2).arr.length 动态监测数组元素
5.数组中新增元素
(1).修改length长度,新增数组元素,length属性是可以读写的,增加空间没有值,默认值undefined
(2).修改数组索引,不要直接给数组名赋值,否则里面的数组元素都没有了。
6.删除数组末尾元素 pop(),数组末尾添加 push(),数组的开头添加,Unshift(),数组开头删除,shift(),数组任意位置添加删除替换截取,splice(索引,删除元素个数),splice(要插入位置索引,删除元素个数,要插入的元素),splice(要替换元素索引,要删除元素,要替换的元素),splice(截取的起始位置,终止位置(不包含)),检索,.indexOf().返回索引.没有返回-1。lastIndexOf(),从后往前。concat(),用于合并数组,reverse(),翻转数组。join(),数组转为字符串。字符串转数组,Array.from().逗号一并转,数字可以转数组但是为空。转数组必须有length,有length但不是数组,就是伪数组。
数组名.forEach(function (v) {//一个个取 遍历数组
console.log(v)
}
6.冒泡排序:可以按照从小到大或者从大到小排序,依次次比较两个元素,顺序有误就换过来,
for(var i = 0;i <= arr.length - 1;i++){//外层循环管趟数
for (var j = 0;j <= arr.length - i -1;j++){//每一趟的交换次数
if (arr[j] < arr[j+1]){
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
console.log(arr);
里层循环最大次数,长度-i-1,i代表趟数,通过外层循环得出
7.把length属性改成只读。
Object.defineProperty(数组名,'length',{writable:false})
十、函数
1.函数就是封装了一段可以被重复执行的代码块。就是让大量代码可以重复使用。
2.声明函数,function 函数名(){函数体},函数命名一般使用动词。
3.调用函数:函数名();
4.函数的封装:把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。就像快递打包
5.函数的参数:
(1).形参,在声明函数的小括号中的时形参形式上的参数形参是接受实参的:aru =’'类似于一个变量.
(2).实参,在函数调用的小括号中是实参,实际的参数
(3).形参和实参的执行过程
(4).函数参数可有可无,数量不限
(5).作用,在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去
注意点:
(1).多个参数之间用逗号隔开
(2).形参可以看作是不用声明的变量
(6).形参和实参个数可以不匹配
function getSum(num1,num2) {console.log(num1 + num2); }
a.如果实参的个数多于形参的个数,会取到形参的个数,几个形参对应几个实参getSum(1,2,3,4);
b.如果实参的个数小于实参的个数,多余的形参定义为undefined 最终结果是NaN,形参可以看作是不用声明的变量,num2 是一个变量但是没有接受值,就跟就是undefined,
getSum(1);//NaN
c.尽量让实参的个数和形参的个数相匹配
6.函数的返回值:
(1).我们函只是实现某种功能,最终结果需要返回给函数调用的函数名(),通过return实现
(2).只要函数遇到return就把后面的结果返回给函数的调用者函数名()= return后面的结果
(3).在我们实际开发中,我们经常使用一个变量来接受函数的返回结果使用更简单
(4).注意事项:
a.return 后面的代码不会被执行
b.return 只能返回一个值
c.如果函数有return 有则返回 return 后的值,没有则返回undefined
d.break:退出当前的循环体(如:for,while),continue:跳出本次循环,继续执行下次循环(如 for,while),return:不仅可以退出循环,还能返回return语句中 的值,同时还可以结束当前函 数体的代码。
7.arguments的使用:当我们不确定有点多少个参数传递时,可以用arguments来获取,在JS中,arguments实际上它是当前函数的一个内置对象,所有函数都内置了一个arguments对象,arguments对象中存储了传递过来的所有实参。
function fn() {console.log(arguments);//里面存储了所有传递过来的实参,
console.log(arguments.length);
console.log(arguments[2]);
for (var i = 0;i <= arguments.length;i++){
console.log(arguments[i]);
}}
fn(1,2,3);
arguments展示形式是一个伪数组。因此可以进行遍历,只有函数才有arguments对象,而且每个函数都内置了arguments,我们可以按照数组 的方式遍历arguments。
伪数组特点:
1.具有length属性
2.按索引方式存储数据
3.不具有数组的push,pop等方法
8.函数可以调用另外一个函数:
9.函数的两种声明方式
(1).利用函数关键字自定义函数
(2).函数
10.作用域:就是变量在某个范围内起作用和效果,目的是为了提高程序的可靠性,更重要的是减少命名冲突
js的作用域(es6)之前:全局作用域,局部作用域
全局作用域:整个script标签,或者是一个单独的js文件
局部作用域,在函数内部就是局部作用域,这个代码的名字只在函数内起作用
11.变量的作用域:
全局变量 :注意如果在函数内部没有声明直接复制的变量也是全局变量。
局部变量:函数的形参也可以看作局部变量
执行效率:全局变量只有浏览器关闭的时候才会销毁,比较占内存
局部变量 当我们程序执行完毕就会销毁,比较节约内存资源;
12.作用域链:根据在内部函数可以访问外部函数变量这种机制,用链式查找决定哪些数据能被函数访问,就称作作用域链,内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称之为作用域链,就近原则,站在目标出发,一层一层往外找
十一、预解析
1.预解析:我们js引擎运行js分两步:预解析,代码执行,预解析js引擎会把js里面作用的var值还有function 提升到当前作用域 的最前面,代码执行按照代码书写的顺序从上往下执行。
坑一:
console.log(num);//返回undefined,
var num = 10;
//相当于执行了以下代码
var num;
console.log(num);
var num = 10;
坑二:
fun()//报错 坑2
var fun = function () {
console.log(22);
}
//相当于执行了以下代码
var fun;
fun();//报错,放到函数表达式声明下即可
fun = function () {
console.log(22);
}
fun();
//函数表达式,调用必须写在函数表达式下面
2.预解析分为 变量预解析(变量提升)和函数预解析(函数提升):
1.变量提升就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作。
2.函数提升就是把所有的函数声明提升到当前作用域的最前面,不调用函数。
案例:
f1();
onsole.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
//相当于以下顺序执行
function f1() {
var a;
a = b = c = 9;
//相当于var a = 9;b = 9;c = 9;b 和 c直接赋值没有var声明,当全局变量看。
//集体声明 var a = 9,b = 9, c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);
十二、JS对象
1.对象:一个具体的事物。由属性和方法组成,属性:特征,方法:行为
2.创建对象:
(1).对象字面量:var obj = {},创建了一个空对象
var obj = {
uname: '张三丰',
age: 18,
sex: '男',
sayHi:function () {
console.log('hi');
}
}
console.log(obj.uname);
console.log(obj['age']);
obj.sayHi();
a.里面 的属性或者方法我们采取的是键值对的形式 键 属性名 : 值 属性值
b.多个属性或者方法用逗号隔开
c.方法冒号后面跟的是一个匿名函数
使用对象
a.调用对象的属性 对象名.属性名
b.调用 属性还有一种方法 对象名[‘属性名’]
c.调用对象的方法 对象名.方法名()
注意:
1.变量和属性的相同点,他们都是用来存储数据的,不同点:变量单独声明并赋值,单独存在,属 性在对象里面的不需要声明,使用时必须是 对象.属性。
2.函数和方法的相同点,都是是实现某种功能 做某件事,不同点:函数是单独声明并且调用的, 函数名() 单独存在的,方法在对象里面 调用的时候 对象.方法()
**(2).**new Object 创建对象
var obj = new Object();
obj.uname = 'shy';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function () {
console.log('hi');
}
console.log(obj.uname);
console.log(obj['sex']);
obj.sayHi();
a.我们是利用等号赋值的方法,添加对象的属性和方法
b.没个属性和方法之间用分号结束
c.利用构造函数创建对象:因为前面两种创建对象的方式一次只能创建一个对象,里面很多属性和方法是大量相同的,因此我们可以利用函数的方法,重复这些相同的代码,我们把这个函数称为构造函数,里面封装的是对象,构造函数就是把我们对心里面的一些相同的属性和方法抽象除了封装到函数里面。以下:
function Stu(uname, age , sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function (sang) {
console.log(sang);
}
}
var shy = new Stu('shy',18,'男');//调用函数函数返回一个对象
console.log(shy);
注意:
(1).构造函数首字母要大写
(2).构造函数不需要return,就可以返回结果
(3).我们调用构造函数必须使用new
(4).我们只有new Stu() 调用函数就创建了一个对象 shy {}
(5).我们的属性和方法前面必须使用this
构造函数和对象:对象是一个具体的事物,构造函数是泛指某一大类,类似Java中的类。构造函数,抽象了公共部分,封装到了函数里面。创建对象,new关键字创建对象的过程称为对象的实例化。
3.new关键字执行过程
(1).new构造函数可以在内存中创建一个空的对象
(2).this就会指向刚才创建的对象
(3).执行构造函数里面的代码,给这个空间对象添加属性和方法
(4).返回这个对象
4.遍历对象属性
(1).对象可以让代码结构更加清晰
(2).对象是复杂数据类型object
(3).本质就是一组无序的相关属性和方法的集合
(4).构造函数泛指某一大类
(5).对象实例特指一个事物,实例化
(6).for in语句用于对象的属性进行循环操作,我们使用for in 里面的变量 我们喜欢写k 或者key
var obj = {
name:'shy',
age:18,
sex:'男',
fn:function () {}
}
//for in 遍历对象
// for(遍历 in 对象){}
for(var k in obj){
console.log(k);//k变量,输出得到属性名
console.log(obj[k]);//obj[k]得到里面的属性值
}
十三、JS的内置对象
JS对象分三种,自定义对象,内置对象,浏览器对象。前面两种属于ECMAScript;第三个浏览器对象属于我们JS独有的,JS API中有讲解。
1.内置对象:JS提供了一些常用方法和功能,可直接使用,帮助我们快速开发。MathDateArrayString
2.查阅文档:MDN
3.Math对象
直接使用,参数可有可无,后跟数字类型,非数字返回NaN,没有参数返回-Infinity
利用对象封装自己的数学对象 里面有PI,最大值,最小值
var myMath = {
PI: 3.14,
max: function () {
var max = arguments[0];
for (var i = 1;i <arguments.length;i++){
if (arguments[i] > max){
max = arguments[i];
}
}
return max;
},
min: function () {
var min = arguments[0];
for (var i = 1;i <arguments.length;i++){
if (arguments[i] < min){
min = arguments[i];
}
}
return min;
}
}
console.log(myMath.PI);
console.log(myMath.max(1,5,9));
console.log(myMath.min(1,5,9));
取整方法:
(1).Math.floor():向下取整
(2).Math.cell():向上取整
(3).Math.round():四舍五入
Math.around(-1.5)
结果为-1,其他数字都是四舍五入,但是.5特殊,往大了取
4.Math.random():返回一个随机的小数,在0-1之间,[0,1),这个方法中不跟参数。
要得到两个数之间的随机整数,并包含这两个数
Math.floor(Math.random()*(max - min +1)) + min
function getRandom(min,max) {
return Math.floor(Math.random() * (max - min + 1))+min;
}
console.log(getRandom(1,10));
用处:随机点名
var arr = ['shy','shy1','shy2','shy3','shy4','shy5'];
console.log(arr[getRandom(0,arr.length - 1)]);
5.日期对象:是一个构造函数,必须使用new 来创建日期对象
(1).使用date, 如果没有参数,则返回系统当前时间
(2).参数常用写法,数字型 :2021,01,01 或者是字符串型:‘2020-1-1 0:0:0’
(3).日期格式化
console.log(date.getFullYear());//返回当前日期的年
console.log(date.getMonth()+1);//返回当前月份(0-11),月份得+1
console.log(date.getDate());//返回的是几号
console.log(date.getDay());//周一返回的是1,周日返回0
var year = date.getFullYear();
var month = date.getMonth()+1;
var dates = date.getDate();
var arr = ['周日','周一','周二','周三','周四','周五','周六'];
var day = date.getDay();
console.log(year+'年'+month+'月'+dates+'日'+arr[day]);
返回当前的时分秒格式 08:08:08
function getTime() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0'+ h : h;
var m = time.getMinutes();
m = m < 10 ? '0'+ m : m;
var s = time.getSeconds();
s = s < 10 ? '0'+ s : s;
return h+':'+ m +':' + s;
}
console.log(getTime());
倒计时效果
(1).核心算法:输入时间减去现在时间就是剩余时间,即倒计时,但是不能拿着时分秒相减,比 如,05分减去25分,结果会是负数。
(2).用时间戳来做,用户输入时间的总毫秒数减去现在时间的总毫秒数,得到的就是剩余时间的毫 秒数
(3).把剩余时间总的毫秒数转换为天、时、分、秒、(时间戳转换为时分秒)
转换公式如下:
(1).d = parseInt(总秒数 / 60 / 60 /24);//计算天数
(2).h = parseInt(总秒数 / 60 / 60 % 24);//计算小时
(3).m = parseInt(总秒数 / 60 % 60);//计算分数
(4).s = parseInt(总秒数%60);//计算当前秒数
倒计时算法
function countDown(time) {
var nowTime = +new Date();//返回的时当前时间总的的毫秒数
var inputTime = +new Date(time);//返回用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000;//times是剩余时间总的秒数
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 +'秒';
}
console.log(countDown('2021-1-16 14:00:00'))
6.数组对象:
Array 创建数组的两种方式
(1).利用数字字面量
var arr = [1,2,3];
(2).利用new Array(2) ,里面有两个空的数组元素,
new Array(2,3)//这样写表示里面有两个数组元素
(3).检测是否为数组:
a.instanceof 运算符,用来监测是否为数组
b.Array.isArray(参数) 用于确定传递的值是否为Array,H5新增,IE9以上版本。
添加删除数组元素的方法
(1).push() 在我们数组的末尾,添加一个或多个元素,
a. push是可以给数组追加新的元素
b. push()参数直接写数组元素就可以了
c. push完毕后,返回的结果是新数组的长度,原数组也会发生变化
(2).unshift 在我们数组 的开头添加一个或多个元素。
var arr =[1,2,3];
arr.unshift('red','purple');
console.log(arr);
a. unshift是可以给数组添加新的元素
b. unshift()参数直接写数组元素就可以了
c. unshift完毕后,返回的结果是新数组的长度
d. 原数组也会发生变化
(3).pop() 它可以删除数组最后一个元素,一次只能删一个。
a. pop是可以删除数组最后一个元素,一次只能删一个
b. pop()没有参数
c. pop完毕后,返回的结果是删除的哪个元素
d. 原数组也会发生变化
(4).shift() 它可以删除第一个元素
a.shift是可以删除数组第一个元素,一次只能删一个
b.shift()没有参数
c.shift完毕后,返回的结果是删除的哪个元素
d.原数组也会发生变化
数组排序
(1).翻转数组
var arr = [1,2,3];
arr.reverse();
console.log(arr);
(2).数组排序(冒泡排序)
var arr1 = [13,3,4,6,1];
arr1.sort(function (a,b) {
return a - b;//按照升序的顺序排序 b - a 是降序排列
});
console.log(arr1);
(3).数组索引方法
返回数组元素索引方法,indexOf(数组元素) 作用就是返回该元素的索引号
lastIndexOf,从后面开始查找它只返回第一个满足条件 的索引号,如果在该数组里面找不到元素, 则返回-1.
var arr = ['red','green','blue','pink','blue'];
var arr = ['red','green','pink'];
console.log(arr.indexOf('blue'));
var arr = ['red','green','blue','pink','blue'];
console.log(arr.lastIndexOf('blue'));//4
(4).数组去重
核心算法:遍历旧数组,然后拿着旧数组去查询新数组,如果该元素在新数组没有出现过,我们就 添加,否则不添加。利用新数组indexOf(数组元素) 如果返回是 -1 ,就说明新数组里面没有该元素
封装一个函数 unique 独一无二的:
function unique(arr) {
var newArr = [];
for (var i = 0; i < arr.length;i++){
if(newArr.indexOf(arr[i]) == -1){
newArr.push(arr[i]);
}
}
return newArr;
}
var arr = unique(['red','green','blue','pink','blue','red','green','blue']);
console.log(arr);
(4).数组转换为字符串:
a. toString() 将我们的数组转换为字符串
var arr = [1,2,3];
console.log(arr.toString());
b. join(分隔符)
var arr1 = ['red','green','blue','pink']
console.log(arr1.join());//red,green,blue,pink
console.log(arr1.join('-'));//red-green-blue-pink
console.log(arr1.join('&'));//red&green&blue&pink
7.字符串对象
(1).基本包装类型
对象才有属性和方法,复杂数据类型才有属性和方法
基本包装类型就是把简单数据类型包装成为了复杂数据类型
就可以使用属性和方法,以下三步:
a.把简单数据类型包装为复杂数据类型
var temp = new String('andy');
b.把临时变量的值给str
str = temp;
c.销毁临时变量
temp = null;
(2).字符串不可变:指的是里面的值不可变,随人看上去可以改变内容,但其实是地址变了,内存中 新开辟了一个内存空间。
var str = 'andy';
console.log(str);
str = 'red';
console.log(str);
//因为我们字符串的不可变,所以不要大量的拼接字符串
var str = '';
for (var i = 0;i <= 100;i++){
str += i;
}
(3).根据字符返回位置:字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成是 会返回一个新的字符串,indexOf,lastIndexOf
返回字符位置
思路:
1.先查找第一个o出现的位置
2.然后,只要indexOf()返回的结果不是-1就继续往后查找
3.因为indexOf只能查找到第一个,所以后面的查找,利用第二个参数当前索引加一,从而继续 查找
var str = "dasofasodjfkhoasldfkoo";
var index = str.indexOf('o');
var num = 0;
console.log(index);
while (index !== -1){
console.log(index);
num++;
index = str.indexOf('o',index + 1);
}
console.log(num);
(4).根据位置返回字符(重点):
1.charAt(index) 根据位置返回字符
var str = 'andy';
console.log(str.charAt(3));
//遍历所有的字符
for (var i = 0;i < str.length;i++){
console.log(str.charAt(i));
}
//charCodeAt(index) 返回相应索引号的字符ASCII值
// 目的:判断用户按下了哪个键
console.log(str.charCodeAt(0))//97
//str[index] H5新增
console.log(str[0]);//a
(5).字符串拼接及截取字符串
substr('截取字符串起始位置','截取几个字符')
var str1 = '改革春风吹满地';
console.log(str1.substr(2,2))//第一个2 是索引号的2 ,从第几个开始
(6).替换字符串及转换为数组
a.替换字符 replace(‘被替换的字符’,‘替换为字符’),它只会替换第一个字符
var str = 'andyandy';
console.log(str.replace('a','b'))
例2:
//把字符串'abcoefoxyozzopp'把里面所有的o替换为*
var str1 = 'abcoefoxyozzopp';
while(str1.indexOf('o') != -1){
str1 = str1.replace('o','*');
}
console.log(str1);
//用于过滤敏感词
b.字符串转换为数组 split(‘分隔符’) join是把数组转换为字符串
//只有隔开才能分
var str2 = 'red,yellow,blue';
console.log(str2.split(','));
var str3 = 'red&yellow&blue';
console.log(str3.split('&'));
十四、JS简单类型与复杂类型,面试问题
1.简单类型(值类型):简单数据/基本数据类型,在存储变量中存储的是值本身,因此叫做值类型
string,number,boolean,undefine,null(返回的是一个空对象 object)
(如果有个变量我们以后打算存储为对象,暂时没有想好放啥,这个时候就给null)
2.引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象(系统对象,自定义对象),如Object,Array,Date等
3.堆栈空间分配区别
(1).栈(操作系统):由操作系统自动分配释放存放的参数值,局部变量的值相等。其他操作方式类似 于数据结构中的栈,简单数据类型存放到栈里面
(2).堆(操作系统):存储复杂类型(对象),一般有程序员分配释放,若程序员不释放,由垃圾回收 机 制回收。复杂数据类型存放到堆里面。
注意:JS中没有对堆栈的概念,通过堆栈的方式更容易理解。
4.简单类型的内存分配,放到栈里面,.(string,number,boolean,undefine,null),里面直接开辟一个空间存放的是一个值。声明了一个变量,在栈里开辟一个空间,存入值,然后让变量名指向这个值。
5.复杂数据类型首先在栈里面存放地址,十六进制表示,然后这个地址指向堆里面的数据。引用类型变量(栈空间)里存放的是地址,真正的对象存放在堆空间中。
6.简单类型传参
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);//a = 11,x = 10;
只传值,不会相互影响
函数的形参也可以看作一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的–值--复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
7.复杂数据类型传参
function Person(name) {
this.name = name;
}
function f1(x){//x = p
console.log(x.name);//刘德华
x.name = "张学友";
console.log(x.name);//张学友
}
var p = new Person('刘德华');
console.log(p.name);//刘德华
f1(p);
console.log(p.name);//张学友
函数的形参也可以看作一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆–地址–复制给了形参,形参和实参其实保存的是一个堆地址,所以操作的是同一个对象,最后的数据也会发生变化。
十五、案例:统计出现次数最多的字符
1.有一个对象 来判断是否有该属性,方法:对象[‘属性名’]
var o = {
age:18
}
if (o['sex']){
console.log('有该属性');
}else {
console.log('没有该属性');
}
2.判断一个字符串’abcoefoxyozzopp’中出现最次数最多的字符,并统计其次数
核心算法:利用charAt()遍历这个字符串,把每个字符串都存储给对象,作为属性,如果对象没有该属性,就为1,如果存在了就+1,最后遍历对象,得到最大值和该字符。
o.a = 1;//a出现了一次,循环一次判断一次,判断一次然后存在的话+1,如果只存在过一次 则赋值为1。
o.b = 1;//b出现了一次
o.c = 1;//c出现了一次
o.o = 4;//o出现了4次
实现:
var str = 'abcoefoxyozzopp';
var o = {};//给了个对象,把数组中每个字符全部取出做为对象的属性
for (var i = 0;i < str.length;i++){
var chars = str.charAt(i);//chars 是字符串的每一个字符
if (o[chars]){//得到的是属性值,判断对象的属性是否存在,如果存在+1,不存在赋值1
o[chars]++;
} else {
o[chars] = 1;
}
}
console.log(o);
//遍历对象
var max = 0;//存最大值
var ch = '';
for (var k in o){
//k是遍历的属性
//k得到的是属性名
//o[k]得到属性值
if (o[k] > max){
max = o[k];
ch = k;
}
}
console.log(max);//返回重复次数最多的字母的--次数--
console.log(ch);//返回最多的字符
结语:基础部分完结,接下来就是进阶部分,尽情期待~