一、js注释:
单行注释://这是单行注释写法
多行注释:/*这是多行注释写法*/
二、数据类型以及变量:
1、变量:
变量不仅可以是数字,还可以是任意数据类型。变量名由大小写英文
、数字
、$
和_
组成,且不能是数字开头
。也不可以是js的关键字
。
变量声明:声明一个变量用var
var a; // 申明了变量a,此时a的值为 undefined
使用 =
对变量进行赋值,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同数据类型的变量,但是注意只能用var
声明一次。
var a = 123; // a的值是整数123
a = 'ABC'; // a变为字符串
var $b = 1; // 申明了变量$b,同时给$b赋值,此时$b的值为1
var s_007 = '007'; // s_007是一个字符串
var Answer = true; // Answer是一个布尔值true
var t = null; // t的值是null
这种变量本身类型不固定的语言称之为动态语言。
打印变量:
var = 100;
console.log(x);
使用console.log()
代替alert()
的好处是可以避免弹出烦人的对话框。
strict严格模式:
在strict模式
下,强制js代码要通过var
声明变量,未使用var
声明变量就使用的,将导致运行错误。
启用strict模式:'use strict';
这是一个字符串,要想启用strict模式,就写在js代码的第一行。
2、数据类型:
JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分.
JavaScript有多少种数据类型?
JavaScript有九种数据类型,这九种数据类型又分为两大类,分别是值类型(基本类型)和引用数据类型。
原始类型(基本类型、标准类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型、构造器类型):对象(Object)、数组(Array)、函数(Function)。
注意: null、undefined是特殊值 。Symbol是ES6引入的一种新的原始数据类型,表示独一无二的值。
常见内置对象:Object、Array、Date、Function、RegExp、Error等;
自定义对象:使用 new Object() 创建或字面形式创建(大括号内定义属性、属性值);
引用类型的值是保存在内存中的对象。
基本类型中的 number、string、boolean 都有对应的包装类型。
JavaScript拥有动态类型:
JavaScript拥有动态类型,这意味着 相同的变量可用作不同的类型:
实例:
var x; // x 为 undefined
var x = 5; // 现在 x 为数字
var x= “John”; // 现在 x 为字符串
2.1、Number
js不区分整数和浮点数,统一用Number表示,以下都是合法的Number类型:
123; // 整数123
0.456; // 浮点数0.456
1.2345e3; // 科学计数法表示1.2345x1000,等同于1234.5
-99; // 负数
NaN; // NaN表示Not a Number,当无法计算结果时用NaN表示
注意:NaN
是个特殊的Nember,它与其它值都不相等,包括他自己:
NaN === NaN; // false。
唯一能判断NaN的方法是通过isNaN()函数:
isNaN(NaN); //true
Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity
Number可以直接做四则运算,规则和数学一致:
1 + 2; // 3
(1 + 2) * 5 / 2; // 7.5
2 / 0; // Infinity
0 / 0; // NaN
10 % 3; // 1
10.5 % 3; // 1.5
注意:%
是取余。
2.2、字符串
字符串是以单引号或双引号括起来的任意文本,
如:
‘abc’,‘123’,‘Abc246我是字符串’,“I’m OK!”
如果'
本身也是一个字符,那就可以用""
括起来。
如果字符串内部既包含’又包含"怎么办?
可以用转义字符\
来标识,
比如:
'I\‘m \“OK\”!’; 表示字符串内容是:I’m “OK”!
转义字符\
可以转义很多字符,比如 \n表示换行,\t表示制表符。
2.2.1、多行字符串
由于多行字符串用\n
写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用反引号`…`表示:
`这是一个
多行
字符串`;
注意:反引号在键盘的ESC下方,数字键1的左边
2.2.2、模板字符串
要把多个字符串连接起来,可以用+
号连接:
var name = '小明';
var age = 20;
var message = '你好, ' + name + ', 你今年' + age + '岁了!';
alert(message);
但是如果有很多变量需要连接,用+
号就显得比较麻烦,ES6新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);
2.2.3、操作字符串
JavaScript为字符串提供了一些常用方法,
注意:调用这些方法本身不会改变原有字符串的内容
,而是返回一个新字符串
:
var s = 'Hello, world!';
(1)length()
:返回字符串的长度:
s.length; // 13 获取字符串的长度
(2)str[index]
:获取指定位置的字符:
s[12]; // '!' 获取字符串某个指定位置的字符,使用类似Array的下标操作,索引号从0开始
s[13]; // undefined 超出范围的索引不会报错,但一律返回undefined
需要特别注意的是,字符串是不可变
的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果:
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然为'Test'
(3)toUpperCase()
把一个字符串全部变为大写:
var s = 'hello';
var upper = s.toUpperCase(); // 返回'HELLO'并赋值给变量upper
upper; // 'HELLO'
(4)toLowerCase()
把一个字符串全部变为小写:
var s = 'Hello';
var lower = s.toLowerCase(); // 返回'hello'并赋值给变量lower
lower; // 'hello'
(5)concat()
字符串拼接,将两个或多个字符串组合起来,返回一个新的字符串:
var a = "hello";
var b = ",world";
var c = a.concat(b);
c; //c = "hello,world"
(6)indexOf()
返回字符串中一个子串第一处出现的索引(从左到右搜索)。如果没有匹配项,返回 -1 :
var s = 'hello, world';
s.indexOf('world'); // 返回7
s.indexOf('World'); // 没有找到指定的子串,返回-1
(7)lastIndexOf()
返回字符串中一个子串最后一处出现的索引(从右到左搜索),如果没有匹配项,返回 -1 :
var a = "hello";
var index1 = lastIndexOf('l');
//index1 = 3
var index2 = lastIndexOf('l',2)
//index2 = 2
(8)charAt()
返回指定位置的字符:
var a = "hello";
var get_char = a.charAt(0);
//get_char = "h"
(9)提取字符串substring、substr、slice
,返回指定索引区间的子串
substring()
返回字符串的一个子串,传入参数是起始位置和结束位置:
var s = 'hello, world'
s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello'
s.substring(7); // 从索引7开始到结束,返回'world'
substr()
返回字符串的一个子串,传入参数是起始位置和长度:
var s = 'hello, world'
var s1 = s.substr(1);
//s1 = "ello"
var s2 = s.substr(1,4);
//s2 = "ello"
slice()
提取字符串的一部分,并返回一个新字符串(与 substring 相同):
var sub_string1 = a.slice(1);
//sub_string1 = "ello"
var sub_string2 = a.slice(1,4);
//sub_string2 = "ell"
(10)匹配一个正则表达式 match 、 replace 、search
match()
检查一个字符串匹配一个正则表达式内容,如果没有匹配返回 null。
var a = "hello";
var b = ",world";
var re = new RegExp(/^\w+$/);
var is_alpha1 = a.match(re);
//is_alpha1 = "hello"
var is_alpha2 = b.match(re);
//is_alpha2 = null
replace()
用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。
var result1 = a.replace(re,"Hello");
//result1 = "Hello"
var result2 = b.replace(re,"Hello");
//result2 = ",world"
var str="Visit Microsoft!"
str.replace(/Microsoft/, "W3School")
// Visit W3School!
search()
执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。
var index1 = a.search(re);
//index1 = 0
var index2 = b.search(re);
//index2 = -1
(11)split
字符串变成数组
通过将字符串划分成子串,将一个字符串做成一个字符串数组
var arr1 = a.split("");
//arr1 = [h,e,l,l,o]
2.3、布尔值
布尔值只有true
和false
两种值,它要么是true
,要么是false
。可以直接用true
、false
表示布尔值,也可通过布尔运算计算出来:
true; // 这是一个true值
false; // 这是一个false值
2 > 1; // 这是一个true值
2 >= 3; // 这是一个false值
2.3.1、或、与、非:||、&&、!
||
:或运算,只要其中有一个true,结果就是true。
false || false; // 这个||语句计算结果为false
true || false; // 这个||语句计算结果为true
false || true || false; // 这个||语句计算结果为true
&&
:与运算,只有所有都是true,结果才是true。
true && true; // 这个&&语句计算结果为true
true && false; // 这个&&语句计算结果为false
false && true && false; // 这个&&语句计算结果为false
!
:非运算,它是一个单目运算符,把true变成false,false变成true。
! true; // 结果为false
! false; // 结果为true
! (2 > 5); // 结果为true
布尔值经常用在条件判断中,比如:
var age = 15;
if (age >= 18) {
alert('成年人');
} else {
alert('未成年');
}
2.4、数组
数组是一组按照顺序排列的有序集合
,集合的每个值称为元素
。js的数组可以是任意数据类型
,并通过索引来访问每个元素。比如:
var arr = [1, 2, 3.14, 'hi', null, true];
arr[0]; // 返回索引为0的元素,即1
arr[5]; // 返回索引为5的元素,即true
arr[6]; // 索引超出了范围,返回undefined
另一种创建数组的方法:Array();
new Array(1, 2, 3); // 创建了数组[1, 2, 3]
但是出于代码可读性,建议直接使用[ ];
。
var arr = [1, 2, 3.14, 'Hello', null, true];
2.4.1、操作数组
(1)要取得Array的长度,直接访问length属性:
var arr = [1, 2, 3.14, 'Hello', null, true];
arr.length; // 6
注意,直接给Array
的length
赋一个新的值会导致Array大小的变化
:
var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]
(2)Array可以通过索引把对应的元素修改为新的值,因此,对Array的索引进行赋值会直接修改这个Array
var arr = ['A', 'B', 'C'];
arr[1] = 99;
arr; // arr现在变为['A', 99, 'C']
注意:如果通过索引赋值时,索引超过了范围
,同样会引起Array大小的变化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
在编写代码时,不建议直接修改Array的大小
,访问索引时要确保索引不会越界。
(3)Array可以通过元素获取到他的索引
indexOf()
,与String类似,Array也可以通过indexOf()
来搜索一个指定的元素
的位置:
var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); // 元素10的索引为0
arr.indexOf(20); // 元素20的索引为1
arr.indexOf(30); // 元素30没有找到,返回-1
arr.indexOf('30'); // 元素'30'的索引为2
(4)Array可以通过切片
slice()
就是对应String的substring()版本,它截取Array的部分元素
,然后返回一个新的Array
:
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']
arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']
注意:slice()
的起止参数包括开始索引
,不包括结束索引
。
如果不给slice()
传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个Array
:
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var aCopy = arr.slice();
aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
aCopy === arr; // false
(5)Array可以通过unshift
和shift
对数组头部添加或删除元素
如果要往Array的头部添加若干元素,使用unshift()
方法,shift()
方法则把Array的第一个元素删掉:
var arr = [1, 2];
arr.unshift('A', 'B'); // 4 返回Array新的长度: 4
arr; // ['A', 'B', 1, 2]
arr.shift(); // 'A' 返回删掉得元素
arr; // ['B', 1, 2]
arr.shift(); arr.shift(); arr.shift(); // 连续shift 3次
arr; // []
arr.shift(); // undefined 空数组继续shift不会报错,而是返回undefined
arr; // []
(6)Array可以通过push
和pop
对数组末尾进行添加或删除元素
push()
向Array的末尾添加若干元素
,pop()
则把Array的最后一个元素删除掉
:
var arr = [1, 2];
arr.push('A', 'B'); // 4 返回Array新的长度: 4
arr; // [1, 2, 'A', 'B']
arr.pop(); // pop()返回'B'
arr; // [1, 2, 'A']
arr.pop(); arr.pop(); arr.pop(); // 连续pop 3次
arr; // []
arr.pop(); // undefined 空数组继续pop不会报错,而是返回undefined
arr; // []
(7)Array可以通过sort
进行排序
sort()
可以对当前Array进行排序
,它会直接修改当前Array的元素位置
,直接调用时,按照默认顺序排序:
var arr = ['B', 'C', 'A'];
arr.sort();
arr; // ['A', 'B', 'C']
(8)Array可以通过reverse
进行反转操作
reverse()
把整个Array的元素给调个个,也就是反转:
var arr = ['one', 'two', 'three'];
arr.reverse();
arr; // ['three', 'two', 'one']
(9)Array可以通过splice
修改元素
splice()
方法是修改Array的“万能方法”
,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
(10)可以通过concat
连接两个Array
concat()
方法把当前的Array和另一个Array连接起来,并返回一个新的Array
:
var arr = ['A', 'B', 'C'];
var added = arr.concat([1, 2, 3]);
added; // ['A', 'B', 'C', 1, 2, 3]
arr; // ['A', 'B', 'C']
注意:concat()
方法并没有修改
当前Array,而是返回了一个新的
Array。
实际上,concat()
方法可以接收任意个元素和Array,并且自动把Array拆开,然后全部添加到新的Array里:
var arr = ['A', 'B', 'C'];
arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]
(11)Array可以通过join
拼接为一个字符串
join()
方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来
,然后返回连接后的字符串:
var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3' // 返回一个字符串,不改变原来得数组
如果Array的元素不是字符串,将自动转换为字符串后再连接。
2.4.2、多维数组
如果数组的某个元素又是一个数组Array,则可以形成多维数组
,例如:
var arr = [[1, 2, 3], [4, 5, 6], '-'];
上述Array包含3个元素,其中前两个元素本身也是数组。
小结:
Array提供了一种有序存储一组元素的功能,并可以按索引来读写。
练习:在新生欢迎会上,你已经拿到了新同学的名单,请排序后显示:欢迎XXX,XXX,XXX和XXX同学!:
'use strict';
var arr = ['小明', '小红', '大军', '阿黄'];
console.log('欢迎'+arr[0]+','+arr[1]+','+arr[2]+'和'+arr[3]+'同学!'); //欢迎小明,小红,大军和阿黄同学!
console.log(`欢迎${arr[0]},${arr[1]},${arr[2]}和${arr[3]}同学!`); //欢迎小明,小红,大军和阿黄同学!
2.5、对象
js用一个花括号{。。。}
表示一个对象,js对象是一组由若干键值对
组成的无序集合
,比如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
'middle-school': 'No.1 Middle School',
zipcode: null
};
注意:最后一个键值对不需要在末尾加 ,
,如果加了,有的浏览器(如低版本的IE)将报错。
javascript对象的键都是字符串类型
,值可以是任意数据类型
。上边的person对象一共定义了7个键值对,其中每个键又称为对象的属性
。
例如:person的name属性为‘Bob’,age属性为20。
获取一个对象的属性,方法是:对象变量.属性名;如:
person.name; // 'Bob'
person.zipcode; // null
(1)访问属性:通过.
操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用''
括起来
person的属性名middle-school不是一个有效的变量,就需要用''
括起来。访问这个属性也无法使用.
操作符,必须用['xxx']
来访问:
person['middle-school']; // 'No.1 Middle School'
person['name']; // 'Bob'
person.name; // 'Bob'
也可以用person['name']
来访问person的name属性,不过person.name
的写法更简洁。我们在编写JavaScript代码的时候,属性名尽量使用标准的变量名,这样就可以直接通过object.prop
的形式访问一个属性了。
访问一个不存在的属性会返回什么呢?
JavaScript规定,访问不存在的属性不报错,而是返回undefined
。
'use strict';
var xiaoming = {
name: '小明'
};
console.log(xiaoming.name);//小明
console.log(xiaoming.age); // undefined
由于JavaScript的对象是动态类型
,可以自由地给一个对象添加或删除属性:
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一个age属性
xiaoming.age; // 18
delete xiaoming.age; // 删除age属性
xiaoming.age; // undefined
delete xiaoming['name']; // 删除name属性
xiaoming.name; // undefined
delete xiaoming.school; // 删除一个不存在的school属性也不会报错
(2)in
关键字,如果我们要检测xiaoming是否拥有某一属性,可以用in
操作符:
var xiaoming = {
name: '小明',
birth: 1990,
school: 'No.1 Middle School',
height: 1.70,
weight: 65,
score: null
};
'name' in xiaoming; // true 自有属性
'grade' in xiaoming; // false
"toString" in o; // true,是一个继承属性
不过要小心,如果in
判断一个属性存在,这个属性不一定是xiaoming的,它可能是xiaoming继承
得到的:
'toString' in xiaoming; // true
因为toString定义在object对象中
,而所有对象最终都会在原型链上指向object
,所以xiaoming也拥有toString
属性。
(3)对象的 hasOwnProperty()
方法:只能判断自有属性是否存在,对于继承属性会返回false。
要判断一个属性是否是xiaoming自身拥有
的,而不是继承得到的,可以用hasOwnProperty()
方法:
var xiaoming = {
name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
(4)条件语句中直接判断
var o={};
if(o.x) o.x+=1; // 如果x是 undefine、null、false、""、0、-0、NaN,它将保持不变
// 判断是否空对象
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
3、类型判断
JavaScript 的数据类型可以分为:基本类型和对象类型。
基本类型:undefined、null、string、number、boolean
引用类型:Object、Array、Date、Function、RegExp、Error
总结:判断基本类型用 typeof
(null 除外),判断引用类型用 instanceof
。通用判断基本类型和引用类型用Object.prototype.toString.call()
。
3.1 typeof
typeof
运算符可以返回一个值的数据类型。
数值、字符串、布尔值分别返回number、string、boolean。
适用: 基本类型 (null 除外)。
不适:对象类型(function 除外)。
特殊:typeof null 返回“object”(这是 JavaScript 最初实现中的一个错误,然后被 ECMAScript
沿用了。现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值)。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
typeof("1"); // "string"
typeof(1); // "number"
typeof(true); // "boolean"
typeof(undefined); // "undefined"
typeof(null); // "object",竟然把 null 当作了对象
typeof({}); // "object"
typeof([]); // "object"
typeof(new Date()); // "object"
typeof(new Function()); // "function",竟然认出了函数
typeof(/\d/); // "object"
typeof(new Error()); // "object"
3.2 instanceof
适用:内置对象、自定义对象
不适:基本类型
坑:不同 window 或 iframe 之间的对象类型检测不能使用 instanceof。 基于原型链操作:obj instanceof
Object。 使用 instaceof 和
construcor,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array
== object.constructor;会返回false; 原因: 1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。 2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
原理:判断左边的左操作数的对象的原型链上是否有右边这个构造函数的prototype属性。
左操作数为对象,不是就返回false,右操作数必须是函数对象或者函数构造器,不是就返回typeError异常。
3.3 Object.prototype.toString
适用:基本类型(null 和 undefined 除外)、内置对象
不适:自定义对象
兼容性:IE6/7/8 检测 null 或 undefined 返回“[object Object]”,若忽视 IE 可使用。
console.log(Object.prototype.toString.call(null)) IE6/7/8 期望[object
Null],但返回[object Object]
// 谷歌浏览器测试
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(1); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(new Function()); // "[object Function]"
Object.prototype.toString.call(/\d/); // "[object RegExp]"
Object.prototype.toString.call(new Error()); // "[object Error]"