JavaScript是一种解释型脚本语言,目的是能够在客户端的网页中增加动态效果和交互能力,实现了用户与网页之间的一种实时的、动态的交互关系。
它最初是由网景公司设计的,起名为LiveScript,后来Java语言非常红火,网景公司希望借助Java的名气来推广,改名为JavaScript,但是除了语法有点相似,在其他部分基本上没啥关系。
后来,JavaScript被Netscape公司交给ECMA制定标准,成为ECMAScript,最新版ECMAScript6(简称ES6)已经在2015年6月正式发布了。
主要用于网页特效、服务端开发、命令行工具、桌面程序、APP、控制硬件—物联网、游戏开发
<input type="button" value="按钮" onclick="alert('Hello World')" />
<script>
alert('Hello,world!');
script>
由包含的代码就是JavaScript代码,他将直接被浏览器执行。
<script type="text/javascript" src="/js/Hello.js">script>
把代码放在单独的文件中更有利于维护代码,并且多个页面可以各自引用同一个.js文件。
JavaScript语法和Java相似,每个语句以;结束,语句块用{···}。
注意:JavaScript严格区分大小写。
变量的概念: 一个变量就是分配了一个值的参数。使用变量可以方便的获取或者修改内存中的数据
变量的声明: 在声明变量时使用关键字var
,要注意关键字与变量名之间的空格,也可以在一行中声明多个变量,以逗号分隔变量。
var age;
var age, name, sex;
age = 10;
name = 'zs';
注意: 变量名必须是一个JavaScript标识符,应遵循以下标准命名规则:
变量的赋值: 在JavaScript中,使用=
对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同的数据类型的变量,但是只能用var
申明一次。要显示变量,可以用console.log(x)
,打开Chrome的控制台就可以看到结果。
var age;
age = 18;
var age=18;
以//开头直到行末的字符被视为注释,注释是给开发人员看的,JavaScript引擎会自动忽略。
另一种块注释是用/*
···*
/把多行字符包裹起来,视为注释。
例如:
<html>
<head>
<script> //这是一行注释
alert('Hello,world!');
/*从这里开始是块注释
块注释结束*/
script>
head>
<body>
···
body>
html>
JSd的数据类型分为两大类:
JavaScript不区分整数和浮点数,统一用number表示,以下都是合法的number类型:
123;//整数123
0.456;//浮点数0.456
1.2345e3;//等同于1234.5
-99;//负数
NaN;//当无法计算结果是使用NaN表示
Infinity;//表示无限大
number存在精度问题:
0.2 + 0.1 = 0.30000000000000004
0.1 + 0.2 !== 0.3 //true
所以最好不要判断浮点数是否相等。
NaN:Not a Number 不是一个number
NaN==NaN ==>false
isNaN():判断是否是number类型
isNaN(NaN) ===> true
isNaN(10) ===> false
isNaN("10") ===> false //将字符串隐性的转换为number类型
isNaN(false) ===> false //将boolean转为number类型
数值转换有多种方法:
console.log(Number(true)); //1
console.log(Number(1)); //1
console.log(Number(undefined)); //NaN
console.log(Number(null)); //0
console.log(Number("123")); //123
console.log(Number('-1')); //-1
console.log(Number("1.1")); //1.1
console.log(Number("011")); //11
console.log(Number(".1")); //0.1
console.log(Number("0xf")); //15
console.log(Number("123a")); //NaN
console.log(Number("a123")); //NaN
console.log(Number("a.1")); //NaN
console.log(Number("0xabc")); //2748
console.log(Number("0xabg")); //NaN
console.log(Number("")); //0
0x
开头所组成的字符串,符合要求可看作十六进制数,然后进行转换,结果为十进制parseInt("1234blue"); //1234
parseInt(""); //NaN
parseInt("0xA"); //10
parseInt("070"); //70
parseInt(true); //NaN
parseInt("22.5"); //22
parseInt(22.5); //22
parseInt("a123"); //NaN
在ECMAScript 3中,parseInt(“070”);的结果为56,因为他将以0开头的看作八进制进行转换,而ES5已经不具备解析八进制的能力,所以我们可以通过给parseInt()传递参数来解决这个问题(通过参数来说明要转换的数据是几进制)
parseInt("070",8); //56
parseInt("AF",16); //175
parseFloat("0xA"); //0
parseFloat("22.34.5"); //22.34
parseFloat("3.125e7"); //31250000
parseFloat("123a"); //123
parseFloat(true); //NaN
+"123" //123
-"123" //123
+ true //1
+"123abc" //NaN
-0
操作时,也会隐性的进行数值转换'123'-0 //123
true-0 //1
'123abc'-0 //NaN
用于表示由零个或多个16位Unicode字符组成的字符序列,即字符串。字符串是以单引号'
或双引号"
括起来的任意文本,比如'abc'
、"xyz"
等等。单引号和双引号只是一种表示方式,不是字符串的一部分,所以,字符串'abc'
中只有a、b、c这3个字符。
特点: 不可变的
当重新为一个字符串赋值时,实际上是重新开辟内存空间,例如:
var lang="Java";
lang=lang+"Script";
以上代码是先创建一个空间存放字符串“Java”,接着在运行到下一行代码时,在内存中重新开辟一个空间,存放的是"JavaScript",变量lang指向新开辟的空间。这些操作都是后台发生的,影响网站性能,所以一般代码中不要写大量的字符串拼接。
转为字符串的方法有:
var num=10;
num.toString(); //"10"
num.toString(2); //"1010"
num.toString(8); //"12"
num.toString(10); //"10"
num.toString(16); //"a"
String(10); //"10"
String(true); //'true'
String(null); //'null'
18+"" //"18"
true+"" //'true'
布尔值和布尔代数的表示完全一样,一个布尔值只有true和false两种值,区分大小写。可以直接用true和false表示布尔值,也可以通过布尔运算算出来:
true;//这是一个true值
false;//这是一个false值
2>1;//这是一个true值
2>=3;//这是一个false值
Boolean()
将一个值转换为其对应的boolean值
转为false的值:
布尔值经常用在条件判断句中。
null
表示一个“空”的值,他和0以及空字符串’‘不同,0是一个数值,’'表示长度为0的字符串,而nul表示空。
undefined
表示“未定义”。
一组数据和功能的集合。可以通过执行new操作符后跟要创建的对象类型的名称来创建,而创建Object类型的实例并为其添加属性或方法。
var student={
name:'LullabyLY',
age:20,
num:xxxxxxxx
};
//也可以是
var student=new Object();
student.name='LullabyLY';
...
要获取一个对象的属性,我们用对象变量.属性名的方法:
student.name;//'LullabyLY'
student.num;//xxxxxxxx
object的每个实例都有下列属性或方法:
获取变量类型,返回的值是string类型
结果有:
typeof 10 //"number"
typeof "10" //"string"
function fn(){
...
}
typeof fn //"function"
//age未声明
typeof age //"undefined"
typeof null //"object"
typeof undefined //"undefined"
typeof将null的类型定为object是因为 null被认为是空的对象引用
操作符包括:
一元操作符只有一个操作数
1.递增(++)和递减(–)操作符
可用于字符串、布尔值、浮点数、整数和对象,操作数自加1或自减1
分为:前置型、后置型
var age=29;
++age; //30
--age; //29
var age=29;
age++; //30
age--; //29
单独看不能发现两者的区别,看以下例子,能够明显的看出前置与后置的区别:
var age1=29;
var anotherAge1= --age + 2; //30
var age2=29;
var anotherAge2= age-- + 2; //31
递增和递减操作遵循规则:
应用于包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作
应用于不包含有效数字字符的字符串时,将变量的值设置为NaN
应用于boolean值时,先将其转换为数值,在执行操作
应用于浮点数时,直接执行操作
应用于对象时,先调用valueOf(),如果结果正确,直接执行操作;如果结果为NaN,调用toString()在执行操作
2.一元加减操作
一元加(+)、减(-)操作符:
var s1 = +"01"; //1
var s2 = +1.1; //1.1
var s3 = +"1.1"; //1.1
var s4 = +"z; //NaN
var s5 = +false; //0
var s6 = {
valueOf:function(){
return -1;
}
};
s6=+s6; //-1
var s1 = -"01"; //-1
var s2 = -1.1; //-1.1
var s3 = -"1.1"; //-1.1
var s4 = -"z; //NaN
var s5 = -false; //0
var s6 = {
valueOf:function(){
return -1;
}
};
s6=-s6; //1
按内存中表示数值的位来操作数值,先将64位的值转换为32位,执行位操作,再转换回64位数值
NaN、Infinity当0来处理,非数值调用Number()
var num=25;
num=~num; //-26
var result=25 & 3; //1
以上例子是将25和3转换位二进制,逐位进行AND操作
var result=25 | 3; //27
var result=25 ^ 3; //26
var num=2;
num=num<<5; //64
以上例子是将2转为二进制10,将10向左移动5位,添0,即1000000,就是二进制的64
var num=64;
num=num>>5; //2
var num=-2;
num=num>>5; //-1
var num=-64;
num=num>>>5; //134217726
&&
运算是与运算,只有所有都为true,&&运算结果才是true;var found=true;
var result=found&&someElement; //报错
var found=false;
var result=found && someElement; //不会发生错误,result为false
||
运算是或运算,只要其中有一个true,||运算结果都为true;var found=true;
var result=found || someElement; //不会发生错误,结果为true
var found=false;
var result=found || someElement; //报错
!
运算是非运算,他是一个单目运算符,把true变成false,把false变为true;!false; //true
!"blue"; //false
!0; //true
!NaN; //true
!""; //true
!12345; //false
!!
模拟Boolean()转型函数,获得一个值对应的布尔值
var num=5+5; //10
var result=5+"5"; //55
var num1=5;
var num2=10;
var message="The sum of 5 and 10 is "+num1+num2;
//"The sum of 5 and 10 is 510"
var num1=5-true; //4
var num2=NaN-1; //NaN
var num3=5-3; //2
var num4=5-""; //5
var num5=5-"2"; //3
var num6=5-null; //5
小于(<)、大于(>)、小于等于(<=)、大于等于(>=)
实际上,JavaScript允许对任意数据类型作比较,但特别要注意相等于算符。JavaScript在设计时,有两种比较运算符:
第一种是==
,它会自动转换类型再比较。!=
:不相等
第二种是===
,他不会自动转换类型,如果两个表达式(包括他们的数据类型)相等,则结果为true。!==
:不全等
注意: NaN与其他的值都不想等,包括他自己,唯一能判断NaN的方法是通过isNaN()
函数:
isNaN(NaN);//true
最后要注意的浮点数的比较:
1/3===(1-2/3);//false
浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算他们之差的绝对值,看是否小于某个阙值:
Math.abs(1/3-(1-2/3))<0.0000001;//true
null==undefined //true
"NaN"==NaN //false
5==NaN //false
NaN==NaN //false
NaN!=NaN //true
false==0 //true
true==1 //true
true==2 //false
undefined==0 //false
null==0 //false
"5"==5 //true
null===undefined //false
条件操作符就是三元表达式。
variable=boolean_expression?true_value:false_value
var max=(num1>num2)?num1:num2
上面的例子是说,当num1大于num2时,max等于num1,否则等于num2
简单的赋值操作符就是=
,其作用就是把右边的值赋给左边的变量
复合赋值操作符:
使用逗号操作符可以在一条语句中执行多个操作
var num1=1,num2=9,num4=8;
var num=(5,6,7,2,0);//num=0
ECMA-262规定了一组语句,也叫做流控制语句
if (/* 条件表达式 */) {
// 执行语句
}
if (/* 条件表达式 */){
// 成立执行语句
} else {
// 否则执行语句
}
if (/* 条件1 */){
// 成立执行语句
} else if (/* 条件2 */){
// 成立执行语句
} else if (/* 条件3 */){
// 成立执行语句
} else {
// 最后默认执行语句
}
do {
// 循环体;
} while (循环条件);
代码示例:
// 初始化变量
var i = 1;
var sum = 0;
do {
sum += i;//循环体
i++;//自增
} while (i <= 100);//循环条件
// 当循环条件为true时,执行循环体,
// 当循环条件为false时,结束循环。
while (循环条件) {
//循环体
}
代码示例:
// 计算1-100之间所有数的和
// 初始化变量
var i = 1;
var sum = 0;
// 判断条件
while (i <= 100) {
// 循环体
sum += i;
// 自增
i++;
}
console.log(sum);
while和do…while一般用来解决无法确认次数的循环。for循环一般在循环次数确定的时候比较方便
for循环语法:
// for循环的表达式之间用的是;号分隔的,千万不要写成,
for (初始化表达式1; 判断表达式2; 自增表达式3) {
// 循环体4
}
执行顺序:1243 ---- 243 -----243(直到循环条件变成false)
案例:
//打印正方形
// 使用拼字符串的方法的原因
// console.log 输出重复内容的问题
// console.log 默认输出内容介绍后有换行
var start = '';
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
start += '* ';
}
start += '\n';
}
console.log(start);
for(property in expression) statement
实例:
循环输出对象的值
var o={
name:"ly",
age:23,
sex:'女'
}
for(var key in o){
console.log(o[key]);
}
label:statement
示例
start:for(var i=0;i<count;i++){
alert(i);
}
这个示例中定义的start标签可以在将来由break、continue语句引用。加标签的语句一般都要与for循环语句配合使用
实例:
var num = 0;
outPoint:
for (var i = 0 ; i < 10 ; i++){
for (var j = 0 ; j < 10 ; j++){
if( i == 5 && j == 5 ){
break outPoint;
}
num++;
}
}
alert(num);
var num=0;
for(var i=1;i<10;i++){
if(i%5==0){
break;
}
num++;
}
alert(i); //4
var num=0;
for(var i=1;i<10;i++){
if(i%5==0){
continue;
}
num++;
}
alert(i); //8
with (expression) statement;
实例:
var qs=location.search.substring(1);
var url=location.href;
//用with语句
with(location){
var qs=search.substrinf(1);
var uel=href;
严格模式下不允许使用with语句,将视为语法错误
switch (expression) {
case 常量1:
语句;
break;
case 常量2:
语句;
break;
case 常量3:
语句;
break;
…
case 常量n:
语句;
break;
default:
语句;
break;
}
break可以省略,如果省略,代码会继续执行下一个case
switch 语句在比较值时使用的是全等操作符, 因此不会发生类型转换(例如,字符串’10’ 不等于数值 10)
函数对任何语言来说都是核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。ECMAScript中的函数由function
关键字来声明,后跟一组参数以及函数体。
语法:
function functionName(arg0,arg1...){
statement
}
示例:
function sayHi(name,message){
alert("Hello "+name+","+message);
}
sayHi("ly","how are you?");//函数的调用
ECMAScript中的函数定义时可以有返回值,也可以没有返回值。当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值
返回值语法:
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参...){
//函数体
return 返回值;
}
//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3);
函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。
返回值详解:
如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined
如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值
如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined
函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退出,也就是说return后面的所有其他代码都不会再执行。
ECMAScript不介意传递的参数的个数,也不在乎参数的数据类型。ECMAScript中的参数是由一个数组来表示的,函数体内部可以通过arguments
对象来访问这个参数数组。arguments对象只是与数组类似(不是Array实例)。
- 形式参数:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
- 实际参数:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
var x = 5, y = 6;
fn(x,y);
function fn(a, b) {
console.log(a + b);
}
//x,y实参,有具体的值。函数执行的时候会把x,y复制一份给函数内部的a和b,函数内部的值是复制的新值,无法修改外部的x,y
变量提升:把变量的声明提升到当前作用域的最上面,不包括赋值
函数提升:将函数的声明提升到当前作用域的最上面,不包括调用
在与解析过程中,如果函数名和变量名相同,函数优先
输出undefined
var a=5;
function num(){
alert(a);
var a=10;
}
num();
/*
* 预解析过程:
* var a;
* function num(){
* var a;
alert(a);
a=10;
}
* a=5;
* num();
* 所以,在调用函数时,先在局部作用域查找a,有a,此时a没有赋值,所以是undefined
* */
输出
ƒ b() {
console.log(b);
}
1
console.log(b);
function b() {
console.log(b);
}
var b=1;
console.log(b);
/*
* 预解析:
* 在预解析过程中,如果函数名和变量名相同,函数优先
* var b;
*function b() {
console.log(b);
}
* console.log(b);
b=1;
console.log(b);*/
输出
1
1
1
1
1
报错
f1();
console.log(y);
console.log(z);
console.log(x);
function f1() {
var x=y=z=1;
console.log(x);
console.log(y);
console.log(z);
}
/*
* var x=y=z=1;
* var x=1;
* y=1;
* z=1;
* */
JS变量、作用域和内存问题
JavaScript基础入门篇(二)