JavaScript基础入门语法
文章目录
一、初识JavaScript
1、编程语言和标记语言的区别
- 编程语言有很强的逻辑和行为能力,在编程语言中,有很多的if else 、for 、while等具有逻辑性和行为能力的指令,这是主动的。包括机器语言、编译语言和高级语言。
- 标记语言不用于向计算机发出指令,常用于格式化和链接,标记语言的存在是用来被读取的,是被动的。
2、JavaScript是什么
- js是世界上最流行的语言之一,是一种运行在客户端的脚本语言(script是脚本的意思)
- 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行来进行解释并执行
- 现在也可以基于Node.js技术进行服务器端编程
3、JavaScript的作用
- 表单动态校验(密码强度检测)js产生的最初目的
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
4、浏览器执行js简介
浏览器分成两部分:渲染引擎和JS引擎
- 渲染引擎:用来解析HTML和CSS,俗称内核,比如Chrome浏览器的blink,老版本的webkit
- JS引擎:也称为JS解释器,用来读取网页中的js代码,对其处理后运行,比如Chrome浏览器的V8
浏览器本身并不会执行js代码,而是通过内置js引擎(解释器)来执行js代码。js引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以js语言归为脚本语言,会逐行解释执行。
5、js的组成
-
ECMAScript
js语法是由ECMA国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为JavaScript 或者JScript,但实际上后两者都是ECMAScript语言的实现和扩展。
-
DOM
页面文档对象模型文档对象模型(Document Object Model) ,是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过DOM提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)
-
BOM
浏览器对象类型浏览器对象模型(Browser Object Model) ,是指浏览器对象模型,它提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
6、js初体验
(1)书写位置
js有3种书写位置:分别为行内、内嵌和外部。
- 行内式
<!-- 行内式的js 直接写到元素内部 -->
<input type="button" value="唐伯虎" onclick="alert('秋香姐')">
- 可以将单行或少量js代码写在HTML标签的事件属性中(以on开头的属性),如
onclick
- 注意单双引号的使用:在HTML中我们推荐使用双引号;而JS中推荐使用单引号
- 可读性差,在html中编写大量js代码时,会不方便阅读
- 引号易错,引号多层嵌套匹配时,非常容易弄混
- 特殊情况下使用
- 内嵌式
<!-- 内嵌式的js -->
<script>
alert('我是编程语言,来控制电脑网页弹出你好');
alert('我是第二行哦');
</script>
- 可以将多行js代码写到
<script>
标签中 - 内嵌js是学习时常用的方式
- 外部
<!-- 引入外部js -->
<script src="my.js"></script>
/*my.js*/
alert('如果我是DJ,你还爱我吗?')
- 利用HTML页面代码结构化,把大段js代码独立到HTML页面之外,既美观又方便文件级别的复用
- 引用外部js文件的script标签中间不可以写代码
<script src="">中间不可以写代码</script>
- 适合于JS代码量比较大的情况
(2)注释
<script>
//单行注释 快捷键:ctrl+'/'
/*多行 快捷键:shift+alt+'a'
注释*/ //也可以在vscode中修改多行注释的快捷键:ctrl+shift+'/' 在键盘快捷方式中进行修改
</script>
(3)输入输出语句
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
// 这是一个输入框
prompt('请输入您的年龄');
// 弹出警示框
alert('计算的结果是');
// console 控制台输出 给程序员测试用的 在网页检查中查看
console.log('我是程序员能看到的');
(4)变量
-
什么是变量
变量就是一个装东西的盒子,用于存放数据的容器,通过变量名获取数据,甚至可以修改数据。
本质是程序在内存中申请的一块用来存放数据的空间。
-
变量的使用
先声明变量 再赋值
声明变量的本质就是去内存申请空间;
变量的初始化:声明变量的同时赋值
//声明变量 var age; //赋值 age=18; //变量的初始化 var age=18; //声明变量的同时赋值
-
声明多个变量
var age=18, myname='kakaxi', address='火影村'
注意:变量不声明直接赋值使用也是可以的,但会变成全局变量。
-
变量命名规范
跟java命名规范相同,不具体写了。
可以用
_ $
作为变量开头,使用驼峰命名法。注意:不要直接使用name作为变量名,因为name比较特殊,虽然既不是关键字也不是保留字,但很多浏览器中name有特殊含义。
二、JavaScript基础
1、数据类型
(1)为什么需要数据类型
因为不同数据所需占用的存储空间不同,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义不同的数据类型。
(2)js数据类型的一些特点
-
js的变量数据类型是程序在运行过程中,根据等号右边的值才能确定下来的
var num = 10; var str = "string"
-
js是动态语言 变量的数据类型是可以变化的
var x = 10;//此时x是数字型 x = "string";//此时x是字符串型
(3)简单数据类型
数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含 整型值和浮点型值 | 0 |
Boolean | 布尔值类型,true/false 0/1 | false |
String | 字符串型 | “” |
Undefined | var a; 声明了变量但未赋值,无法确定类型 | undefined |
Null | var a = null; 声明了变量为空值 | null |
1.Number
八进制和十六进制表示
//数字前面加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
2.String
可以使用单引号,也可以使用双引号。
但因为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 + '岁');
3.Undefined
var variable = undefined;
console.log(variable + 1); //NaN
4.Null
var space = null;
console.log(space + 1); //1
5.Boolean
var flag = true;
console.log(1 + flag); //2
(4)typeof 检测变量数据类型
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都是浅灰色的
字面量:字面量是在源代码中一个固定值的表示法,通俗来讲,就是字面量表示如何表达这个值。
- 数字字面量:8,9,10
- 字符串字面量:‘程序员’,‘前端’
- 布尔字面量:true,false
(5)数据类型转换
使用表单、prompt获取的数据默认是字符串型的,此时就不能直接简单地进行加法运算,而需要转换成数字型的变量。
1.转换为字符串
方式 | 说明 | 案例 |
---|---|---|
toString() | 转换成字符串 | var num=1;alert(num.toString()); |
String() 强制转换 | 转换成字符串 | var num=1;alert(String(num)); |
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num=1;alert(num + ‘’); |
加号拼接字符串的方法也称为隐式转换,是最常用的方法。
2.转换为数字型(重点)
方式 | 说明 | 案例 |
---|---|---|
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
3.转换为布尔型
方式 | 说明 | 案例 |
---|---|---|
Boolean()函数 | 其他类型转换成布尔型 | Boolean(‘true’) |
- 代表空、否定的值会被转换为false,如:
''、0、NaN、null、undefined
- 其余值都会被转换为true
(6)复杂数据类型
见10 简单数据类型和复杂数据类型。
拓展内容1:解释性语言VS编译型语言
将程序语言翻译成机器语言的工具,称为翻译器。翻译器翻译的方式有两种:编译
和解释
,两种方式之间的区别在于翻译的时间点不同。
- 编译器是在代码执行之前进行编译,生成中间代码文件
- 解释器是在运行时进行及时解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)
js就是一种典型的解释性语言。
拓展内容2:标识符、关键字、保留字
- 标识符:就是开发人员为变量、属性、函数、参数取的名字。不能是关键字或保留字。
- 关键字:是指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
等
2、算术运算符
(1)浮点数的精度问题
浮点数的最高精度为17位,但在进行算术运算时精确度远远不如整数。
console.log(0.1 + 0.2);//0.30000000000000004
console.log(0.07 * 100);//7.000000000000001
所以:不要直接判断两个浮点数是否相等!
(2)前置自增(自减)VS后置自增(自减)
如果单独使用,效果一致。
-
前置自增
先变量自加 表达式再返回值
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
(3)比较运算符
1.== !=
相等和不相等,默认转换数据类型。
console.log(18 == '18'); //true
- 如果操作数是布尔值,则先转换为数值,其中 false 转为 0,true 转换为 1。
- 如果一个操作数是字符串,另一个操作数是数字,则先尝试把字符串转换为数字。
- 如果一个操作数是字符串,另一个操作数是对象,则先尝试把对象转换为字符串。
- 如果一个操作数是数字,另一个操作数是对象,则先尝试把对象转换为数字。
- 如果两个操作数都是对象,则比较引用地址。如果引用地址相同,则相等;否则不等。
注意:NaN与任何值都不相等,包括它自己。null 和 undefined 值相等,但是它们是不同类型的数据。在相等比较中,null 和 undefined 不允许被转换为其他类型的值。
2.=== !==
全等和不全等,全等要求两边的值还有数据类型要完全一致
console.log(18 === '18'); //false
console.log(18 === 18); //true
在全等运算中,应注意以下几个问题:
- 如果两个操作数都是简单的值,则只要值相等,类型相同,就全等。
- 如果一个操作数是简单的值,另一个操作数是复合型对象,则不全等。
- 如果两个操作数都是复合型对象,则比较引用地址是否相同。
对于复合型对象,并不是比较对象的值是否相等,主要是比较引用地址。因此,对于复合对象来说,比较相等和全等的结果是相同的。
(4)逻辑运算符
短路运算(逻辑中断)
**短路运算的原理:**当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值。
1.逻辑与
-
语法:表达式1&&表达式2
-
如果表达式1为真,则返回表达式2
-
如果表达式1为假,则返回表达式1
console.log(123 && 456); //456 console.log(0 && 123); //0
2.逻辑或
- 语法:表达式1 | | 表达式2
- 如果表达式1为真,则返回表达式1
- 如果表达式1为假,则返回表达式2
-
逻辑中断很重要 它会影响我们的运行结果
// 逻辑中断很重要 它会影响我们的运行结果 var num = 0; console.log(123 || num++); //123 console.log(num); //0
(5)运算符优先级
- 一元运算符里面的逻辑非 优先级很高
- 逻辑与 比 逻辑或 优先级高
3、流程控制分支
流程控制主要有三种结构:顺序结构
、分支结构
、循环结构
(1)顺序结构
就是由上到下顺序执行
(2)分支结构
1.三元表达式:由三元运算符组成的式子称为三元表达式
语法结构:条件表达式 ? 表达式1:表达式2
2.switch 语句
switch(表达式) {
case value1: //这里面表达式的值和value1的值需要全等!! ===
执行语句1;
break; //如果当前case里面没有break,则不会退出switch 而是继续执行下一个case
case value2:
执行语句2;
break;
...
default:
执行最后的语句;
}
对比if else if和switch语句
- 一般情况下,两者可以相互替换
- switch…case语句通常处理case是确定值的情况;而if…else语句则更灵活,常用于范围判断
- switch语句进行条件判断后直接执行到程序的条件语句,效率更高;而if…else语句有几种条件,就需要判断几次
- 分支较少时,if…else语句的执行效率比switch语句高
- 分支较多时,switch语句的执行效率比较高,且结构更清晰
(3)循环结构
1.追加字符串:
var str = '';
for (var i = 0; i < 5; i++) {
str += '★';
}
console.log(str);
先声明一个空字符串,然后再追加。
2.continue
for (var i = 1; i <= 5; i++) {
if (i == 3) continue;
console.log('我正在吃第' + i + '个包子');
}
/*我正在吃第1个包子
我正在吃第2个包子
我正在吃第4个包子
我正在吃第5个包子*/
跳过本次循环,不影响后续。
3.break
for (var i = 1; i <= 5; i++) {
if (i == 3) break;
console.log('我正在吃第' + i + '个包子');
}
我正在吃第1个包子
我正在吃第2个包子
跳出整个循环。
4、数组
(1)创建数组
1.利用new创建数组
var arr = new Array();
2.利用数组字面量创建数组
var arr = [];
**注意:**数组元素之间用,
分隔,且无数据类型限制。 var arr = [1,2,'pink',true];
(2)数组新增元素
1.修改length长度
// 修改数组长度 来新增数组元素
var arr = ['red', 'green', 'blue'];
console.log(arr.length);
arr.length = 5;
console.log(arr);
console.log(arr[3]); //新增元素初始默认为undefined
2.修改索引号
// 修改索引 来新增数组元素
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1);
(3)删除数组中指定元素
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是会自动检测数组长度的
5、函数
就是封装了一段可以被重复调用执行的代码块。
(1)函数的使用
函数的使用分为两步:声明函数
和 调用函数
// 1.声明函数
function sayHi() {
console.log('hi~~');
}
// 2.调用函数 函数不调用 自己不执行
sayHi();
函数的两种声明方式:
-
利用函数关键字自定义函数(命名函数)
function fn(){}
-
函数表达式
var fun = function(){}
注意:这里fun是变量名,并不是函数名;该函数没有名字,也称为匿名函数
(2)形参和实参
-
形参:在声明函数的小括号中
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
(3)return
-
终止函数 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
(4)arguments的使用
当我们不确定有多少参数传递的时候,可以用arguments
来获取。在js中,arguments实际上是当前函数的一个内置对象。每个函数都有一个arguments对象,存储了传递的所有实参。
arguments以伪数组的方式存储实参
伪数组:并不是真正意义上的数组
- 具有数组的length属性
- 按照索引方式进行存储
- 没有真正数组的一些方法
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));
(5)函数可以调用另外一个函数
function fn1() {
console.log(111); //111
fn2(); //222 \n fn2
console.log('fn1'); //fn1
}
function fn2() {
console.log(222);
console.log('fn2');
}
fn1();
6、作用域
就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性 更重要的是减少命名冲突。
js的作用域(es6之前):全局作用域和局部作用域
(1)全局作用域
整个script标签 或者 一个单独的js文件
(2)局部作用域
在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用 所以也称为函数作用域
// 全局作用域
var num = 10;
console.log(num); //10
function fn() {
// 局部作用域
var num = 20;
console.log(num); //20
}
fn();
(3)变量的作用域
-
全局变量
全局作用域下的变量 在全局下都可以使用
或者函数内不使用var声明的变量
-
局部变量
在局部作用域下的变量 或者说是在函数内部的变量 只能在函数内部使用
函数形参也是局部变量
function fun() {
var num1 = 30; //num1局部变量 只能在函数内部使用
num2 = 40; //在函数内部 没有声明 直接赋值的变量也是全局变量
}
fun();
// console.log(num1); //Uncaught ReferenceError: num1 is not defined
console.log(num2); //40
注意:函数的形参也可以看做是局部变量!
从执行效率来看全局变量和局部变量:
- 全局变量只有浏览器关闭是才会销毁,比较占内存资源
- 局部变量 当我们程序执行完毕就会销毁,比较节约内存资源
(4)块级作用域
js只包含两种作用域:全局作用域和局部作用域,没有块级作用域。ES6新增了块级作用域。
块级作用域 {} for {} if {}
(5)作用域链
- 只要有代码,就至少有一个作用域
- 根据内部函数可以访问外部函数变量的机制:
用链式查找决定哪些数据能被内部函数访问
,就称为作用域链
其实就是"就近原则"
7、js预解析
js代码是由浏览器中的js解析器来执行的,js解析器(js引擎)在运行js代码的时候分两步:预解析和代码执行。
(1)预解析
js引擎会把js里面所有的var 还有 function提升到当前作用域的最前面
1.变量预解析(变量提升)
就是把所有的变量声明提升到当前作用域最前面 不提升赋值操作
// 先使用变量 后声明
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);
}
2.函数预解析(函数提升)
就是把所有的函数声明提升到当前作用域最前面 不调用函数
// 自定义函数 先调用 后声明
fn(); //11
function fn() {
console.log(11);
}
// 相当于执行了以下代码
function fn() {
console.log(11);
}
fn();
(2)代码执行
按照代码书写的顺序从上往下执行。
(3)预解析练习
-
案例一
// 案例一 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); //报错
8、对象
(1)什么是对象
对象是一个具体的事物。
在js中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
- 属性:事物的特征
- 方法:事物的行为
为了更清晰地表达事物。
(2)创建对象的三种方式
1.利用字面量创建对象
对象字面量:{}
里包含了表达这个具体事物(对象)的属性和方法。
var obj = {
uname: '张三',
age: 18,
sex: '男',
sayHi: function () {
console.log('hi~');
},
sayBye: function () {
console.log('bye~');
}
}
- 对象中的属性和方法使用键值对的方式进行书写
- 多个属性或方法中间使用
,
进行分割 - 方法冒号后,跟着一个匿名函数
2.利用new Object创建对象
var obj = new Object(); //创建了一个空对象
obj.uname = '张三';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function () {
console.log('hi~');
}
- 利用等号 = 赋值的方法 添加对象的属性和方法
- 每个属性和方法用分号结束
3.利用构造函数创建对象
为什么需要使用构造函数?因为前面两种创建对象方式一次只能创建一个对象。
构造函数与普通函数不同,里面封装的不是普通代码,而是对象。构造函数就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面。
语法格式
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,'男');
- 构造函数名首字母要大写
- 构造函数不需要return 就可以返回结果
- 调用构造函数时必须使用new来创建对象
- 属性和方法前面必须添加this
(3)使用对象
-
调用对象的属性
对象名.属性名
或者对象名['属性名']
console.log(obj.uname); console.log(obj['uname']);
-
调用对象的方法
obj.sayHi();
(4)变量VS属性 函数VS方法
-
变量&属性
-
相同:都是用来存储数据的
-
不同
变量 单独声明并赋值 使用时直接写变量名 单独存在
属性 在对象里不需要声明 使用时必须通过
对象.属性
-
-
函数&方法
-
相同:都是事先某种功能 做某件事
-
不同
函数 单独声明并调用 使用时直接写函数名() 单独存在
方法 在对象里 调用时必须通过
对象.方法名()
-
(5)对象VS构造函数
- 对象 特指 是一个具体的事物
- 构造函数 泛指 某一大类
利用构造函数创建对象的过程也称为对象的实例化。
(6)new 关键字
- new 构造函数可以在内存中创建了一个空的对象
- this指向当前创建的空对象
- 执行构造函数中的代码 给这个空对象添加属性和方法
- 返回这个对象
(7)遍历对象中的属性
for (变量 in 对象)
k->key
for (var k in obj) {
console.log(k); //k 变量 输出属性名
console.log(obj[k]); //obj[k] 输出属性值
}
9、内置对象
(1)什么是内置对象
- js中的对象分为3种:
自定义对象、内置对象、浏览器对象
- 前两个对象是js基础内容,属于ECMAScript;第三个浏览器对象是js独有的
- 内置对象就是指js自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本且必要的功能(属性和方法)
- js提供了多个内置对象:
Math、Date、Array、String
等
(2)查文档
可以通过MDN/W3C
查询。MDN: Mozilla 开发网络
提供了有关开放网络技术(Open Web)的信息,包括HTML、CSS和万维网及HTML5应用的API。
如何学习?
- 查阅该方法的功能
- 查看里面参数的意义和类型
- 查看返回值的意义和类型
- 通过demo进行测试
(3)Math对象
不是构造函数,所以不需要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.绝对值
// 1.绝对值
console.log(Math.abs(-1));
console.log(Math.abs('-1')); //会有隐式转换
console.log(Math.abs('pink')); //NaN
- Math对象有隐式转换
- 对于无法进行转换的返回NaN
2.取整
// 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
- 注意round 四舍五入中如果碰上.5 则往大了取;比如round(1.5)取2,而round(-1.5)取-1,而不是-2!
3.随机数
// 3.随机数 返回一个随机小数 0=<x<1 无参数
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
(4)Date对象
日期对象是一个构造函数 必须使用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]);
- 获取年、月、日、星期的方法
- 注意返回月份是从0开始的
- 星期是从星期日开始的 也就是周日会返回0 周一-周六返回1-6
// 时分秒
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());
- 时分秒 如果小于10 则前面补0 使用到字符串拼接
时间戳
获取日期的总的毫秒形式(时间戳):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());
倒计时案例
- 核心算法:输入的时间减去现在的时间就是剩余时间,即倒计时,但是不能拿着时分秒相减,比如05分减去25分,结果会是负数。
- 所以选择使用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
- 再把剩余时间总的毫秒数转换为天、时、分、秒(时间戳转换为时分秒)
(5)Array对象
1.创建对象
// 创建数组
// 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);
2.检测是否为数组
// 检测是否为数组元素
// 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));
- instanceof 运算符
- Array.isArray(参数)
3.添加删除数组元素的方法
// 添加删除数组元素的方法
// 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);
- 添加元素:push() unshift()
- 删除元素:pop() shift()
4.数组排序
// 数组翻转
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);
- 翻转 reverse
- 排序 sort ([compareFunction])
5. 数组元素索引
// 数组元素索引
var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue')); //只返回第一个满足条件的索引号
console.log(arr.indexOf('purple')); //如果没有该元素,则返回-1
console.log(arr.lastIndexOf('blue')); //从后往前查找
6.数组去重
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));
在新数组中查找是否包含当前旧数组元素,如果没有则加入新数组中。
7.数组转换为字符串
// 数组转换为字符串
// 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
- toString()
- join(‘分隔符’) 比toString()方法更强大一些,可以使用自定义的分隔符进行分隔
(6)String对象
1.基本包装类型
为了方便操作基本数据类型,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;
2.字符串不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
因为字符串不可变,所以不要大量地拼接字符串或者是给字符串重新进行赋值
3.根据字符返回位置
字符串所有的方法,都不会修改字符串本身(字符串不可变),操作完成会返回一个新的字符串。
还是indexOf()和lastIndexOf()方法:
// 根据字符返回位置
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春'));
// 其实indexOf()方法有两个参数(第二个参数可选) indexOf('要查找的元素',[起始位置])
console.log(str.indexOf('春', 3)); //从索引号是3的位置开始查找
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));
}
// 2.charCodeAt(index) 返回相应索引号的字符ASCII值 为了判断用户按下了哪个键
console.log(str.charCodeAt(0));
// 3.str[index] H5新增 IE8+支持 与charAt()等效
console.log(str[0]);
5.判断字符串中出现次数最多的字符
// 判断字符串"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);
6.拼接以及截取字符串
// 拼接以及截取字符串
// 1.concat('str1','str2')
var str1 = 'andy';
console.log(str1.concat('red'));
// 2.substr(start,length)
var str2 = '改革春风吹满地';
console.log(2, 2);
7.替换字符串以及转换为数组
// 替换字符串以及转换为数组
// 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('&'));
10、简单数据类型和复杂数据类型
(1)简单数据类型VS复杂数据类型
又称为基本数据类型或者值类型,复杂数据类型又叫做引用类型。
-
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string ,number ,boolean ,undefined ,null
// 简单数据类型null 返回的类型是一个空的对象 object var timer = null; console.log(typeof timer);
如果有个变量我们打算存储为对象 暂时没想好放啥,则可以给null
-
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等
(2)堆和栈
-
栈:由操作系统自动分配释放,存放函数的参数值、局部变量的值等。
简单数据类型存放在栈中,直接开辟一个空间存储值
-
堆:存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,则由垃圾回收机制回收
复杂数据类型存放在堆中,首先在栈里面存放地址(十六进制) 然后这个地址指向堆里面的数据
注意js中没有堆栈概念,只是通过堆栈的方式,更容易理解代码的一些执行方式。
(3)简单数据类型传参
// 简单数据类型传参
function fn(a) {
a++;
console.log(a); //11
}
var x = 10;
fn(x);
console.log(x); //10
(4)复杂数据类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
(有点类似于浅拷贝)
// 复杂数据类型传参
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); //张学友