浏览器分成两部分:渲染引擎和JS引擎
浏览器本身并不会执行js代码,而是通过内置js引擎(解释器)来执行js代码。js引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以js语言归为脚本语言,会逐行解释执行。
ECMAScript
js语法
是由ECMA国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为JavaScript 或者JScript,但实际上后两者都是ECMAScript语言的实现和扩展。
DOM
页面文档对象模型
文档对象模型(Document Object Model) ,是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过DOM提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)
BOM
浏览器对象类型
浏览器对象模型(Browser Object Model) ,是指浏览器对象模型,它提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
js有3种书写位置:分别为行内、内嵌和外部。
<input type="button" value="唐伯虎" onclick="alert('秋香姐')">
onclick
<script>
alert('我是编程语言,来控制电脑网页弹出你好');
alert('我是第二行哦');
script>
标签中
<script src="my.js">script>
/*my.js*/
alert('如果我是DJ,你还爱我吗?')
<script>
//单行注释 快捷键:ctrl+'/'
/*多行 快捷键:shift+alt+'a'
注释*/ //也可以在vscode中修改多行注释的快捷键:ctrl+shift+'/' 在键盘快捷方式中进行修改
script>
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
// 这是一个输入框
prompt('请输入您的年龄');
// 弹出警示框
alert('计算的结果是');
// console 控制台输出 给程序员测试用的 在网页检查中查看
console.log('我是程序员能看到的');
什么是变量
变量就是一个装东西的盒子,用于存放数据的容器,通过变量名获取数据,甚至可以修改数据。
本质是程序在内存中申请的一块用来存放数据的空间。
变量的使用
先声明变量 再赋值
声明变量的本质就是去内存申请空间;
变量的初始化:声明变量的同时赋值
//声明变量
var age;
//赋值
age=18;
//变量的初始化
var age=18; //声明变量的同时赋值
声明多个变量
var age=18,
myname='kakaxi',
address='火影村'
注意:变量不声明直接赋值使用也是可以的,但会变成全局变量。
变量命名规范
跟java命名规范相同,不具体写了。
可以用_ $
作为变量开头,使用驼峰命名法。
注意:不要直接使用name作为变量名,因为name比较特殊,虽然既不是关键字也不是保留字,但很多浏览器中name有特殊含义。
因为不同数据所需占用的存储空间不同,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义不同的数据类型。
js的变量数据类型是程序在运行过程中,根据等号右边的值才能确定下来的
var num = 10;
var str = "string"
js是动态语言 变量的数据类型是可以变化的
var x = 10;//此时x是数字型
x = "string";//此时x是字符串型
数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含 整型值和浮点型值 | 0 |
Boolean | 布尔值类型,true/false 0/1 | false |
String | 字符串型 | “” |
Undefined | var a; 声明了变量但未赋值,无法确定类型 | undefined |
Null | var a = null; 声明了变量为空值 | null |
八进制和十六进制表示
//数字前面加0 表示八进制 输出会以十进制输出
var num1 = 010;
console.log(num1); //8
//数字前面加0x 表示十六进制
var num2 = 0xa;
console.log(num2);
数字型取值范围
//数字型的最大值
console.log(Number.MAX_VALUE);
//数字型的最小值
console.log(Number.MIN_VALUE);
数字型三个特殊值
Infinity
无穷大,大于任何值 console.log(Number.MAX_VALUE * 2); //Infinity
-Infinity
无穷小,小于任何值 console.log(-Number.MAX_VALUE * 2); //-Infinity
NaN
Not a Number 非数值 console.log("str" - 100); //NaN
可以使用单引号,也可以使用双引号。
但因为HTML标签中的属性使用的是双引号,所以js中更推荐使用单引号。
字符串转义符
转义符 | 解释说明 |
---|---|
\n |
换行符,n是newline的意思 |
\\ |
斜杠\ |
\' |
单引号 |
\" |
双引号 |
\t |
tab 缩进 |
\b |
blank 空格 |
字符串长度length
var str = 'my name is andy';
console.log(str.length);
字符串拼接:只要有字符串和其他类型的数据类型拼接,最后都是字符串类型
console.log('沙漠' + '骆驼'); //沙漠骆驼
console.log('12' + 18); //1212
var age = 18;
console.log('pink' + age + '岁');
var variable = undefined;
console.log(variable + 1); //NaN
var space = null;
console.log(space + 1); //1
var flag = true;
console.log(1 + flag); //2
var num = 10;
console.log(typeof num); //number
var timer = null;
console.log(typeof timer); //object 这个比较特殊
注意:prompt取过来的值是 字符串型的
var age = prompt('请输入您的年龄:');
console.log(age); //18
console.log(typeof age); //string
还可以通过控制台输出的颜色来判断变量的类型:字符串是黑色的;数字是蓝色的;布尔型是较深的蓝色;null和undefined都是浅灰色的
字面量:字面量是在源代码中一个固定值的表示法,通俗来讲,就是字面量表示如何表达这个值。
使用表单、prompt获取的数据默认是字符串型的,此时就不能直接简单地进行加法运算,而需要转换成数字型的变量。
方式 | 说明 | 案例 |
---|---|---|
toString() | 转换成字符串 | var num=1;alert(num.toString()); |
String() 强制转换 | 转换成字符串 | var num=1;alert(String(num)); |
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num=1;alert(num + ‘’); |
加号拼接字符串的方法也称为隐式转换,是最常用的方法。
方式 | 说明 | 案例 |
---|---|---|
parseInt(string)函数 | 将string类型转换成整数数值型 | parseInt(‘78’) |
parseFloat(string)函数 | 将string类型转换成浮点数数值型 | parseFloat(‘3.14’) |
Number()强制转换函数 | 将string类型转换成数值型 | Number(‘12’) |
js隐式转换(- * / ) |
利用算术运算隐式转换为数值型 | ‘12’ - 0 |
注意:parseInt()得到的结果是整数,且采取的是直接取整,而不是四舍五入。
parseInt('3.14'); //3 pareseInt('3.94') //3
方式 | 说明 | 案例 |
---|---|---|
Boolean()函数 | 其他类型转换成布尔型 | Boolean(‘true’) |
''、0、NaN、null、undefined
见10 简单数据类型和复杂数据类型。
将程序语言翻译成机器语言的工具,称为翻译器。翻译器翻译的方式有两种:编译
和解释
,两种方式之间的区别在于翻译的时间点不同。
js就是一种典型的解释性语言。
break,case,catch,continue,default,delete,do,else,finally,for,function,if,in,instanceof,new, return,switch,this,throw,try,typeof,var,void,while,with
等boolean,byte,char,class,const,debugger,double,enum,export,extends,final,float,goto, implements,import,int,interface,long,mative,package,private,protected,public,short,static, super, synchronized,throws,transient,volatile
等浮点数的最高精度为17位,但在进行算术运算时精确度远远不如整数。
console.log(0.1 + 0.2);//0.30000000000000004
console.log(0.07 * 100);//7.000000000000001
所以:不要直接判断两个浮点数是否相等!
如果单独使用,效果一致。
前置自增
先变量自加 表达式再返回值
var num = 10;
console.log(++num + 10); //num=11 ++num=11
后置自增
先表达式返回原值 后面变量再自加
var num = 10;
console.log(num++ + 10); //num++10 num=11
练习:
var e = 10;
console.log(e++); //先返回值 再自加 e++=10 e=11
console.log(++e); //先自加 再返回值 e=12 ++e=12
var f = e++ + ++e; //e++=12 e=13 e=14 ++e=14
console.log(f); //f=26
== !=
相等和不相等,默认转换数据类型。console.log(18 == '18'); //true
注意:NaN与任何值都不相等,包括它自己。null 和 undefined 值相等,但是它们是不同类型的数据。在相等比较中,null 和 undefined 不允许被转换为其他类型的值。
=== !==
全等和不全等,全等要求两边的值还有数据类型要完全一致console.log(18 === '18'); //false
console.log(18 === 18); //true
在全等运算中,应注意以下几个问题:
对于复合型对象,并不是比较对象的值是否相等,主要是比较引用地址。因此,对于复合对象来说,比较相等和全等的结果是相同的。
短路运算(逻辑中断)
**短路运算的原理:**当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值。
语法:表达式1&&表达式2
如果表达式1为真,则返回表达式2
如果表达式1为假,则返回表达式1
console.log(123 && 456); //456
console.log(0 && 123); //0
逻辑中断很重要 它会影响我们的运行结果
// 逻辑中断很重要 它会影响我们的运行结果
var num = 0;
console.log(123 || num++); //123
console.log(num); //0
流程控制主要有三种结构:顺序结构
、分支结构
、循环结构
就是由上到下顺序执行
语法结构:条件表达式 ? 表达式1:表达式2
switch(表达式) {
case value1: //这里面表达式的值和value1的值需要全等!! ===
执行语句1;
break; //如果当前case里面没有break,则不会退出switch 而是继续执行下一个case
case value2:
执行语句2;
break;
...
default:
执行最后的语句;
}
对比if else if和switch语句
var str = '';
for (var i = 0; i < 5; i++) {
str += '★';
}
console.log(str);
先声明一个空字符串,然后再追加。
for (var i = 1; i <= 5; i++) {
if (i == 3) continue;
console.log('我正在吃第' + i + '个包子');
}
/*我正在吃第1个包子
我正在吃第2个包子
我正在吃第4个包子
我正在吃第5个包子*/
跳过本次循环,不影响后续。
for (var i = 1; i <= 5; i++) {
if (i == 3) break;
console.log('我正在吃第' + i + '个包子');
}
我正在吃第1个包子
我正在吃第2个包子
跳出整个循环。
var arr = new Array();
var arr = [];
**注意:**数组元素之间用,
分隔,且无数据类型限制。 var arr = [1,2,'pink',true];
// 修改数组长度 来新增数组元素
var arr = ['red', 'green', 'blue'];
console.log(arr.length);
arr.length = 5;
console.log(arr);
console.log(arr[3]); //新增元素初始默认为undefined
// 修改索引 来新增数组元素
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1);
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] != 0) newArr[newArr.length] = arr[i];//注意length是会自动检测数组长度的
}
console.log(newArr);
注意length是会自动检测数组长度的
就是封装了一段可以被重复调用执行的代码块。
函数的使用分为两步:声明函数
和 调用函数
// 1.声明函数
function sayHi() {
console.log('hi~~');
}
// 2.调用函数 函数不调用 自己不执行
sayHi();
函数的两种声明方式:
利用函数关键字自定义函数(命名函数)
function fn(){}
函数表达式
var fun = function(){}
注意:这里fun是变量名,并不是函数名;该函数没有名字,也称为匿名函数
形参:在声明函数的小括号中function 函数名(形参1,形参2...)
形参是接收实参的,类似于一个变量。
实参:在函数调用的小括号中函数名(实参1,实参2...)
如果函数形参和实参个数不匹配
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 100);
//如果实参个数大于形参个数 只取到形参的个数
getSum(1, 2, 3); //3
//如果实参个数小于形参个数 多余的形参默认为undefined 最终的结果为NaN
getSum(1); //NaN
JS中形参的默认值为undefined
终止函数 return后的语句不会被执行
return只能返回一个值
function fn(num1, num2) {
return num1, num2; // 返回结果是最后一个值
}
console.log(fn(1,2)); //2
如果想返回多个值,则可以返回一个数组
function getResult(num1, num2) {
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
var re = getResult(1,2);
console.log(re)
如果函数没有return 则返回undefined
function f2() {
}
cosole.log(f2()); //undefined
当我们不确定有多少参数传递的时候,可以用arguments
来获取。在js中,arguments实际上是当前函数的一个内置对象。每个函数都有一个arguments对象,存储了传递的所有实参。
arguments以伪数组的方式存储实参
伪数组:并不是真正意义上的数组
pop() push()等
demo--利用arguments求任意个数的一组数的最大值
function getMax() {
var max = arguments[0];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] > max) max = arguments[i];
}
return max;
}
console.log(getMax(1, 2, 3));
console.log(getMax(23, 45, 24, 64, 0));
function fn1() {
console.log(111); //111
fn2(); //222 \n fn2
console.log('fn1'); //fn1
}
function fn2() {
console.log(222);
console.log('fn2');
}
fn1();
就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性 更重要的是减少命名冲突。
js的作用域(es6之前):全局作用域和局部作用域
整个script标签 或者 一个单独的js文件
在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用 所以也称为函数作用域
// 全局作用域
var num = 10;
console.log(num); //10
function fn() {
// 局部作用域
var num = 20;
console.log(num); //20
}
fn();
全局变量
全局作用域下的变量 在全局下都可以使用
或者函数内不使用var声明的变量
局部变量
在局部作用域下的变量 或者说是在函数内部的变量 只能在函数内部使用
函数形参也是局部变量
function fun() {
var num1 = 30; //num1局部变量 只能在函数内部使用
num2 = 40; //在函数内部 没有声明 直接赋值的变量也是全局变量
}
fun();
// console.log(num1); //Uncaught ReferenceError: num1 is not defined
console.log(num2); //40
注意:函数的形参也可以看做是局部变量!
从执行效率来看全局变量和局部变量:
js只包含两种作用域:全局作用域和局部作用域,没有块级作用域。ES6新增了块级作用域。
块级作用域 {} for {} if {}
用链式查找决定哪些数据能被内部函数访问
,就称为作用域链其实就是"就近原则"
js代码是由浏览器中的js解析器来执行的,js解析器(js引擎)在运行js代码的时候分两步:预解析和代码执行。
js引擎会把js里面所有的var 还有 function提升到当前作用域的最前面
就是把所有的变量声明提升到当前作用域最前面 不提升赋值操作
// 先使用变量 后声明
console.log(num); //undefined
var num = 10;
// 相当于执行了以下代码
var num;
console.log(num);
num = 10;
// 函数表达式 先调用 后声明
fun(); //报错
var fun = function () {
console.log(22);
}
// 相当于执行了以下代码
var fun;
fun();
fun = function () {
console.log(22);
}
就是把所有的函数声明提升到当前作用域最前面 不调用函数
// 自定义函数 先调用 后声明
fn(); //11
function fn() {
console.log(11);
}
// 相当于执行了以下代码
function fn() {
console.log(11);
}
fn();
按照代码书写的顺序从上往下执行。
案例一
// 案例一
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
// 相当于执行以下代码
var num; //只提升声明
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10; //不提升赋值
fun();
案例二
// 案例二
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
// 相当于执行以下代码
var num;
function fn() {
var num;
console.log(num); //undefined
num = 20;
console.log(num); //20
}
num = 10;
fn();
案例三
// 案例三
var a = 10;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
// 相当于执行以下代码
var a;
function f1() {
var b;
var a;
b = 9;
console.log(a); //undefined
console.log(b); //9
a = '123';
}
a = 10;
f1();
案例四
注意:var a = b = c = 9;
相当于var a = 9; b = 9; c = 9;
如果想集体声明 应使用如下代码var a = 9,b = 9,c = 9;
// 案例四
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
// 相当于var a = 9; b = 9; c = 9;
// 如果想集体声明 应使用如下代码var a = 9,b = 9,c = 9;
console.log(a);
console.log(b);
console.log(c);
}
// 相当于执行以下代码
var b;
var c;
function f1() {
var a;
a = b = c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //报错
对象是一个具体的事物。
在js中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
为了更清晰地表达事物。
对象字面量:{}
里包含了表达这个具体事物(对象)的属性和方法。
var obj = {
uname: '张三',
age: 18,
sex: '男',
sayHi: function () {
console.log('hi~');
},
sayBye: function () {
console.log('bye~');
}
}
,
进行分割var obj = new Object(); //创建了一个空对象
obj.uname = '张三';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function () {
console.log('hi~');
}
为什么需要使用构造函数?因为前面两种创建对象方式一次只能创建一个对象。
构造函数与普通函数不同,里面封装的不是普通代码,而是对象。构造函数就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面。
语法格式
function 构造函数名() {
this.属性 = 值,
this.方法 = function() {}
}
//使用
new 构造函数名()
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sayHi = function () {
console.log('hi~');
}
}
new Star('刘德华',18,'男');
调用对象的属性
对象名.属性名
或者对象名['属性名']
console.log(obj.uname);
console.log(obj['uname']);
调用对象的方法
obj.sayHi();
变量&属性
相同:都是用来存储数据的
不同
变量 单独声明并赋值 使用时直接写变量名 单独存在
属性 在对象里不需要声明 使用时必须通过 对象.属性
函数&方法
相同:都是事先某种功能 做某件事
不同
函数 单独声明并调用 使用时直接写函数名() 单独存在
方法 在对象里 调用时必须通过 对象.方法名()
利用构造函数创建对象的过程也称为对象的实例化。
for (变量 in 对象)
k->key
for (var k in obj) {
console.log(k); //k 变量 输出属性名
console.log(obj[k]); //obj[k] 输出属性值
}
自定义对象、内置对象、浏览器对象
Math、Date、Array、String
等可以通过MDN/W3C
查询。MDN: Mozilla 开发网络
提供了有关开放网络技术(Open Web)的信息,包括HTML、CSS和万维网及HTML5应用的API。
如何学习?
不是构造函数,所以不需要new来调用,而是直接使用里面的属性和方法即可。
console.log(Math.PI); //属性
console.log(Math.max(1, 88, 8));
console.log(Math.max(1, 2, 'pink')); //NaN
console.log(Math.max()); //-Infinity
利用对象封装自己的Math对象 里面有PI、最大值和最小值:
var myMath = {
PI: 3.141592653,
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, 4, 35, 6));
console.log(myMath.min(1, 4, 35, 6));
Math对象不是构造函数,它具有数学常数和函数的属性和方法。
跟数学相关的运算(求绝对值,取整,最大值等)可以使用Math对象中的成员
Math.PI
Math.floor() //向下取整
Math.ceil() //向上取整
Math.round() //四舍五入
Math.abs() //绝对值
Math.random() //随机数
// 1.绝对值
console.log(Math.abs(-1));
console.log(Math.abs('-1')); //会有隐式转换
console.log(Math.abs('pink')); //NaN
// 2.三个取整方法
// (1)floor 向下取整
console.log(Math.floor(1.1));
// (2)ceil 向上取整
console.log(Math.ceil(1.1));
// (3)round 四舍五入
console.log(Math.round(1.4));
// 但.5比较特殊,它往大了取
console.log(Math.round(-1.5)); //结果为 -1
// 3.随机数 返回一个随机小数 0=
console.log(Math.random());
// 我们想得到两个数之间的随机整数 并且包含这两个整数
// 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 = ['张三', '张三疯', '张三疯子', '李四'];
console.log(arr[getRandom(0, arr.length - 1)]);
这里要重点掌握返回两个数之间随机数的写法
Math.floor(Math.random() * (max - min +1)) + min
日期对象是一个构造函数 必须使用new 来调用创建日期对象
// Date 对象
// 无参 则返回当前系统的当前时间
var date = new Date();
console.log(date);
// 数字型参数
var date1 = new Date(2018, 9, 1);
console.log(date1); //返回的是10月 而不是9月
// 字符串型参数
var date2 = new Date('2021-8-8 14:36');
console.log(date2);
无参 则返回当前系统的当前时间
数字型参数
要注意 月份是从0开始的
字符串型参数
日期格式化
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear());
console.log(date.getMonth() + 1);
console.log(date.getDate());
console.log(date.getDay()); //周日会返回0 周一~周六返回1~6
// 写成 年 月 日 星期的格式
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]);
// 时分秒
function getTimer() {
var time = new Date();
var hour = time.getHours();
hour = hour < 10 ? '0' + hour : hour;
var minute = time.getMinutes();
minute = minute < 10 ? '0' + minute : minute;
var second = time.getSeconds();
second = second < 10 ? '0' + second : second;
return hour + ':' + minute + ':' + second;
}
console.log(getTimer());
时间戳
获取日期的总的毫秒形式(时间戳):Date对象是基于1970年1月1日(世界标准时间)起的毫秒数,我们经常利用总的毫秒数来计算时间,因为它更精确。
由于毫秒形式永远不会重复,所以也称为时间戳,可以用于标识。
// 获得Date总的毫秒数 不是当前时间的毫秒数 而是距离1970年1月1日过了多少毫秒数
// 1.通过调用 valueOf() 或者 getTime() 方法
var date = new Date();
console.log(date.valueOf()); // 就是我们现在时间 距离1970年1月1日的总毫秒数
console.log(date.getTime());
// 2.简单写法(最常用的写法)
var date1 = +new Date();
console.log(date1);
// 3.H5 新增写法
console.log(Date.now());
倒计时案例
// 创建数组
// 1.利用数组字面量
var arr = [1, 2, 3];
// 2.利用new Array()
// var arr1 = new Array(); //创建了一个空的数组
// var arr1 = new Array(2); //这里是创建了一个长度为2的数组 里面有两个空的数组元素
var arr1 = new Array(2, 3); //等价于[2,3] 表示里面有两个数组元素,分别是2和3
console.log(arr1);
// 检测是否为数组元素
// 1.instanceof 运算符 可以用来检测是否为数组
var arr = [];
console.log(arr instanceof Array);
var obj = {};
console.log(obj instanceof Array);
// 2.Array.isArray(参数); H5新增方法 IE9以上版本才支持
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
// 添加删除数组元素的方法
// 1.push() 在数组的末尾 添加一个或多个数组元素
var arr = [1, 2, 3];
var push_ret = arr.push(4, 'pink');
console.log(arr);
console.log(push_ret); //push()的返回值为新数组长度
// 2.unshift() 在数组的开头 添加一个或多个数组元素
var unshift_ret = arr.unshift('red');
console.log(arr);
console.log(unshift_ret);
// 3.pop() 删除数组的最后一个元素
var pop_ret = arr.pop();
console.log(arr);
console.log(pop_ret); //pop()的返回值为所删除的元素
// 4.shift() 删除数组的第一个元素
var shift_ret = arr.shift();
console.log(arr);
console.log(shift_ret);
// 数组翻转
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);
// 数组排序
var arr1 = [13, 4, 77, 1, 7];
arr1.sort() //如果单独使用sort() 则返回结果为[1,13,4,7,77] 结果有问题
// 添加参数compareFunction 用于指定按某种顺序进行排列的函数
// 如果省略该参数,则元素按照转换为的字符串的各个字符的Unicode位点进行排序
arr1.sort(function (a, b) {
return a - b; //升序顺序排序
// return b - a; //降序顺序排序
});
console.log(arr1);
// 数组元素索引
var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue')); //只返回第一个满足条件的索引号
console.log(arr.indexOf('purple')); //如果没有该元素,则返回-1
console.log(arr.lastIndexOf('blue')); //从后往前查找
var arr = ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'];
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;
}
console.log(unique(arr));
在新数组中查找是否包含当前旧数组元素,如果没有则加入新数组中。
// 数组转换为字符串
// 1.toString()
var arr = [1, 2, 3];
console.log(arr.toString()); //1,2,3
// 2.join('分隔符')
var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); //green,blue,pink
console.log(arr1.join('-')); //green-blue-pink
为了方便操作基本数据类型,js提供了三个特殊的引用类型:String Number Boolean
基本包装类型就是把简单数据类型包装成复杂数据类型,这样基本数据类型就有了属性和方法
// 基本包装类型 就是把简单数据类型包装称为了复杂数据类型
var str = 'andy';
console.log(str.length);
//本来对象才会有属性和方法 但这里简单数据类型也有length属性
/*在底层眼中 以上代码执行过程如下*/
// (1) 把简单数据类型包装为复杂数据类型
var temp = new String('andy');
// (2) 把临时变量的值 给 str
str = temp;
// (3) 销毁临时变量
temp = null;
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
因为字符串不可变,所以不要大量地拼接字符串或者是给字符串重新进行赋值
字符串所有的方法,都不会修改字符串本身(字符串不可变),操作完成会返回一个新的字符串。
还是indexOf()和lastIndexOf()方法:
// 根据字符返回位置
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春'));
// 其实indexOf()方法有两个参数(第二个参数可选) indexOf('要查找的元素',[起始位置])
console.log(str.indexOf('春', 3)); //从索引号是3的位置开始查找
// 根据位置返回字符
// 1.charAt(index)
var str = 'andy';
console.log(str.charAt(3));
// 遍历所有的字符
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i));
}
// 2.charCodeAt(index) 返回相应索引号的字符ASCII值 为了判断用户按下了哪个键
console.log(str.charCodeAt(0));
// 3.str[index] H5新增 IE8+支持 与charAt()等效
console.log(str[0]);
// 判断字符串"abcoefoxyozzopp"中出现次数最多的字符 并统计其次数
var str = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < str.length; i++) {
// 利用charAt()遍历字符串
var chars = str.charAt(i);
// 把每个字符都存储给对象,如果对象没有该属性,则为1;如果存在则+1
if (o[chars]) {
o[chars]++;
} else {
o[chars] = 1;
}
}
console.log(o);
// 遍历对象,得到最大值和该字符
var max = 0;
var ch = '';
for (var k in o) {
if (o[k] > max) {
max = o[k];
ch = k;
}
}
console.log(ch);
console.log(max);
// 拼接以及截取字符串
// 1.concat('str1','str2')
var str1 = 'andy';
console.log(str1.concat('red'));
// 2.substr(start,length)
var str2 = '改革春风吹满地';
console.log(2, 2);
// 替换字符串以及转换为数组
// 1.替换字符 replace('被替换的字符','替换为的字符')
var str = 'andyandy';
console.log(str.replace('a', 'b')); //注意只会替换第一个a
// 替换字符串中所有的o为*
var str1 = 'abcoefoxyozzopp';
while (str1.indexOf('o') !== -1) {
str1 = str1.replace('o', '*');
}
console.log(str1);
// 2.字符转换为数组 split('分隔符') 跟前面学过的join('分隔符')区分 这个是把数组转换为字符串
var str2 = 'red,pink,blue';
console.log(str2.split(','));
var str2 = 'red&pink&blue';
console.log(str2.split('&'));
又称为基本数据类型或者值类型,复杂数据类型又叫做引用类型。
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string ,number ,boolean ,undefined ,null
// 简单数据类型null 返回的类型是一个空的对象 object
var timer = null;
console.log(typeof timer);
如果有个变量我们打算存储为对象 暂时没想好放啥,则可以给null
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等
栈:由操作系统自动分配释放,存放函数的参数值、局部变量的值等。
简单数据类型存放在栈中,直接开辟一个空间存储值
堆:存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,则由垃圾回收机制回收
复杂数据类型存放在堆中,首先在栈里面存放地址(十六进制) 然后这个地址指向堆里面的数据
注意js中没有堆栈概念,只是通过堆栈的方式,更容易理解代码的一些执行方式。
// 简单数据类型传参
function fn(a) {
a++;
console.log(a); //11
}
var x = 10;
fn(x);
console.log(x); //10
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
(有点类似于浅拷贝)
// 复杂数据类型传参
function Person(name) {
this.name = name;
}
function f1(x) {
console.log('2' + x.name); //刘德华
x.name = '张学友';
console.log('3' + x.name); //张学友
}
var p = new Person('刘德华');
console.log('1' + p.name); //刘德华
f1(p);
console.log('4' + p.name); //张学友