js的一切如变量,函数名,操作符都区分大小写。
首字符必须是字母或下划线或$,其他字符除了前面3个,还有数字。
两种:
//单行注释
/*
* 多行注释
*/
ES5引入了严格模式,在任意位置写上如下代码,即开启严格模式,严格模式下,某些代码执行会抛出异常。
"use strict";
js代码结束不用添加;号,但是建议添加上,这样不容易出错,压缩代码时也方便。
var message = 'hi';//动态类型,用var表示,没有确切类型
message = 2;//还可以等于数字
message2 = 'hi2';//可以不添加var,直接给变量赋值,相当于创建了全局变量
function test() {
var message = 'hi';//局部变量,message仅在test函数内部可见
message2 = 'hi';//没有var,相当于声明全局变量,函数内外均可见
}
console.log(message); // undefined
console.log(message2); // hi
var message = 'hi', found = true, age = 29;//一行声明多个变量
5种简单数据类型:Undefined, Null, Boolean, Number, String.
1种复杂数据类型:Object
console.log(typeof 'hi'); // string
console.log(typeof message); // undefined, 未定义的变量
var obj = null;
console.log(typeof obj); // object
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof function(){}); // function
这种类型只有一个值,undefined:
var message;
console.log(message);// undefined, 声明但未赋值
var message2 = undefined;
console.log(message2);// undefined, 直接赋值为undefined
"use strict";//这句话放到文件顶部或者函数第一行才生效
//未声明的变量使用时直接出错
console.log(age); // ReferenceError: age is not defined,
//未声明变量也输出undefined
console.log(typeof age); // undefined
//删除某个变量,严格模式下出错
delete age;//SyntaxError: Delete of an unqualified identifier in strict mode.
只有一个值:null。
var car = null;
console.log(typeof car); // object
这个类型两个值:true和false。
var found = true, lost = false;
console.log(found, lost);// true false
其它类型可以转换成Boolean类型,使用Boolean()函数:
var msg = 'Hello world';
console.log(Boolean(msg)); // true
数据类型 | 转换为true的值 | 转换为false的值 |
Boolean | true | false |
String | 任何非空字符 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | 不存在 | undefined |
var msg = 'Hello world';
if (msg) { //自动应用上述转换规则,由于字符串不空,直接得true值
console.log('msg is true'); // msg is true
}
两种值,整数和浮点数。
var floatNum1 = 1.1, floatNum2 = 0.1, floatNum3 = .1, floatNum4 = 3.125e7;
console.log(floatNum1, floatNum2, floatNum3, floatNum4); // 1.1 0.1 0.1 31250000
//对于浮点数,千万不要做这样的判断,因为浮点数的特殊存储方式,
//在任何语言里都不会相等的
if (0.1 + 0.2 === 0.3) {
console.log('0.1+0.2 = 0.3');
} else {
console.log('0.1+0.2 !== 0.3');
}
// 当一个浮点数是正数时,能够精确到的范围值如下
console.log(Number.MIN_VALUE, Number.MAX_VALUE);// 5e-324 1.7976931348623157e+308
// 浮点数的正负值范围应该很大,很少能超过这个值,如果超过了,
// 分别用下面两个值表示
console.log(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);//-Infinity Infinity
//使用isFinite来判断一个数是不是超出范围了
console.log(isFinite(Number.POSITIVE_INFINITY), isFinite(2)); // false true
Not a Number,不是一个数值。
// 只有0/0才会出现NaN
console.log(0/0, 2/0, -2/0); //NaN Infinity -Infinity
//注意NaN !== NaN
console.log(NaN === NaN); // false
// isNaN()可以判断一个值是不是数值,它的判断标准是根据的Number()转换规则来的
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false
console.log(isNaN('10')); // false (可以转换成数值10)
console.log(isNaN('blue')); // false (不能转换成数值)
console.log(isNaN(true)); // false (true转换成1)
有3个函数可以把非数值进行转换:Number(), parseInt(), parseFloat()。
数据类型 | 转换规则 |
Boolean | true = 1, false = 0 |
数字值 | 原数字 |
null | 0 |
undefined | NaN |
String | 1. 如果字符串中只包含数字,包括前面的正负号,则转换为十进制数,其中前导的0会被忽略; 2. 如果字符串是有效的浮点格式,转换成对应的浮点值,同样忽略前导0; 3. 如果字符串中包含有效的十六进制,则转换成对应的十进制; 4. 字符串空,转换成0; 5. 其它内容的,转换成NaN; |
Object |
// Boolean 转换
console.log(Number(true), Number(false));// 1 0
// 数字
console.log(Number(1), Number(1.02)); // 1 1.02
// 字符串
console.log(Number('1'), Number('+1'), Number('+011')); // 1 1 11
console.log(Number('+01.1')); // 1.1
console.log(Number('+00xf'), Number('0xf')); // NaN 15
console.log(Number(""), Number('011s'));// 0 NaN
// 对象
let a = {
valueOf: function() {
return '2';
}
}, b = {
valueOf: function() {
return 'b';
},
toString: function() {
console.log('should not print');
return '2';
}
}, c = {
valueOf: function() {
return 'c';
},
toString: function() {
return 'c';
}
}, d = {
toString: function() {
return '2';
}
};
console.log(Number(a), Number(b), Number(c), Number(d));// 2 NaN NaN 2
转换类型 | 转换规则 |
字符串 | 忽略字符串前面的空格,直到找到一个非空格字符。如果该字符不是数字或者正负号, 返回 NaN; 如果是数字,那么继续解析,直到遇到非数字字符。 |
数值 | 取整数部分 |
console.log(parseInt(" -0022"));// -22
console.log(parseInt(' a2')); // NaN
console.log(parseInt('1234blue')); // 1234
console.log(parseInt('')); // NaN
console.log(parseInt(22.5)); // 22
console.log(parseInt('070')); // 70
console.log(parseInt('0xf')); // 15
// parseInt可以传入第2个参数,表示要转换的进制数
console.log(parseInt('0xaf', 16));//175
console.log(parseInt('af', 16));//175
console.log(parseInt('af'));//NaN,没有指定第2个参数
console.log(parseInt('10', 2));// 2
console.log(parseInt('10', 8));// 8
console.log(parseInt('10', 10)); // 10
console.log(parseInt('10', 16)); // 16
类型 | 规则 |
字符串 | 从第1个非空字符开始,直到遇到无效的浮点字符, 小数点也是有效字符。只识别10进制,例如16进制会解析成0。 |
数值 | 转换成对应的值,如果小数点后而是0,则转换成整数 |
console.log(parseFloat('1234blue')); // 1234
console.log(parseFloat(' +002.4')); // 2.4
console.log(parseFloat('0xf')); // 0
console.log(parseFloat(22.5));//22.5
console.log(parseFloat('22.34.5')); // 22.34
console.log(parseFloat('3.125e7')); // 31250000
console.log(parseFloat(22.0)); // 22
用单引号或双引号括起来的16位unicode字符组成的序列。字符串具有不变性,一旦创建成功,是不能再修改的。
var lang = 'Java';
lang = lang + 'Script';// 想修改lang,只能重新赋值一个新的字符串
console.log(lang);// JavaScript
转换字符串有2种方式:
1. 数值,布尔值, 对象和字符串值可以调用toString()方法:
var age = 2, found = true;
console.log(age.toString(), found.toString());// 2 true
// undefined, null不能调用toString()方法,会引起错误
// 数值可以给toString()方法传递参数,表示输出对应的进制数
var num = 10;
console.log(num.toString(2));// 1010
console.log(num.toString(16));// a
2. 使用String()方法
1)如果值有toString()方法,则调用这个方法;
2) 如果是null,返回 ’null';
3)如果是undefined,返回'undefined';
let a = {
toString: function() {
return 'a';
}
}
console.log(String(null), String(undefined), String(a));// null undefined a
中文名对象,是一组数据和功能的集合。有字面量和new两种方式创建:
var obj1 = {};//字面量法,两个花括号
var obj2 = new Object();// new
var obj3 = new Object;// 没有参数,可以省略括号
Object是所有对象的基础,它的实例具有如下属性和方法:
let a = {
age: 12
}, b = Object.create(a);// 把a设置为b对象的原型
b.name = 'henry';
// 属性constructor, 指向创建当前对象的函数
console.log(b.constructor); // [Function: Object]
// 方法 hasOwnProperty(propertyName),检查给定的属性是否存在于当前实例中,而不是原型中
console.log(b.hasOwnProperty('name'));// true
console.log(b.hasOwnProperty('age'));// false
// 方法 isPrototypeOf(object),当前对象是否是object的原型
console.log(a.isPrototypeOf(b));// true
// 方法 propertyIsEnumerable(propertyName), 用于检查给定的属性是否能够使用for-in语句来枚举。
console.log(b.propertyIsEnumerable('name')); // true
//我们创建一个不可枚举的属性
Object.defineProperty(b, 'name2', {
value: 'name2',
enumerable: false
});
console.log(b.name2, b.propertyIsEnumerable('name2'));// name2 false
for (var property in b) {
console.log(property);
}//输出name age,至所以输出age,应该是在原型中它是可枚举的
//但是直接调用propertyIsEnumberable却输出false,我估计这个方法只能检查自身属性,不能
//检查原型中的属性
console.log(b.propertyIsEnumerable('age'));//false
// toLocaleString(), toString(),返回对象的字符串表示形式
// valueOf(),返回对象的字符串、数值或布尔值表示。
//以上的方法是所有对象实例都可以访问的方法。
记住BOM和DOM对象是宿主对象,不一定继承自Object,所以可能不含有上述方法。
就是递增++和递减--,一元+和-,一共这4个。他们可以直接操作Number类型,如果不是Number类型的话,后台会自动按照Number()转换规则转换成Number类型后,再执行操作。
//使用一元+做例子,其他类似
console.log(+'01', +'1.1', +'z', +false, +1.1); // 1 1.1 NaN 0 1.1
let a = {
valueOf: function() {
return 1;
}
}, b = {
valueOf: function() {
return '2'
}
}, c = {//valueOf优先级高于toString()方法,前者失败后,不会再调用后者
valueOf: function() {
return 'a';
},
toString: function() {
return '3';
}
}, d = {
toString: function() {
return '4';
}
};
console.log(+a, +b, +c, +d);//1 2 NaN 4
js中的数值都是64位存储的,位操作时只操作32位,如果操作的对象不是数值,是其它类型,仍然按照Number()规则先转换成数值,再应用位操作,这些操作包含取反~,与&,或|,异或^,左移<<,右移>>,无符号右移>>>。
其实就是应用Boolean()转换规则,然后取反。
console.log(!false, !'blue', !NaN, !'', !12);//true false true true false
记住这个操作是短路操作。一般形式为 操作数1 && 操作数2,如果Boolean(操作数1)为true, 那么返回操作数2,如果Boolean(操作数1)为false,那么返回操作数1。
console.log(NaN && true);// NaN
console.log({} && 2);//2
形式为 操作数1||操作数2,如果Boolean(操作数1)为true,返回操作数1,否则返回操作数2.
console.log(NaN || true); // true
console.log({} || 2);// {}
// || 一般常见于如果某个值为空,那么就给它赋上后面的值。
function func(param) {
var value = param || 'no value';//如果param不存在,就等于'no value';
console.log(value);
}
func('param');// param
func();// no value
要求两个操作数都是数值,如果其中任意一个不是数值,都会应用Number()转换规则,先转换成数值类型,再进行乘法运算,如果运算的结果超出了数值范围,会使用正负无穷大表示,即Infinity或-Infinity。
console.log(Number.MAX_VALUE * Number.MAX_VALUE); // Infinity
console.log(-Number.MAX_VALUE * Number.MAX_VALUE); // -Infinity
console.log(2*'3');//6
console.log('3'*'4'); // 12
console.log('a'*'b'); // NaN
console.log(2 * Number.POSITIVE_INFINITY);// Infinity
与乘法类似。
console.log(6/'3');// 2
console.log('12'/'4'); // 3
console.log('a'/'b'); // NaN
console.log(0/0);// NaN
console.log(2/0);// Infinity
console.log(-2/0);// -Infinity
console.log(Number.POSITIVE_INFINITY/1);// Infinity
与上面的都类似。
如果有一个操作数是字符串,那么就会把另一个也转换为字符串连接起来。
console.log(2+3); // 5
console.log(2+'2'); // 22
console.log(undefined+undefined); // NaN
console.log(null+null);//0
console.log(2+NaN);//NaN
console.log(Infinity + 3);// Infinity
console.log(Infinity + 'a');//Infinitya
与加法类似,不一样的是,减法要求两个操作数都是数值类型,所以如果其中有不是的,会应用Number()转换规则。
console.log(5- true);//4
console.log(NaN-1);//NaN
console.log(4-'2');//2
console.log(5-null);//5
let a = {
valueOf: function() {
return 1;
}
}, b = {
toString: function() {
return '2';
}
}, c = {};
console.log(a-0, b-0, c-0);// 1 2 NaN
包住4种,大于, 小于,大于等于,小于等于。如果两个操作数都是字符串,那么按照字符串的字典序比较大小 ,如果不全是的话,先都按Number()规则转换成数值后再比较。
console.log('23' < '3');// true
console.log('23' < 3); // false
//任何数与NaN比较,结果都是false
console.log(NaN<3, NaN >=3);// false false
有2组操作符:相等和不相等,全等和不全等。
即==和!=两个操作符,比较规则特殊一些:
即===和!==,这两个 操作符要求操作数首先是一种类型,如果类型不同,全等操作一定是false。
console.log('55' == 55);//true
console.log('55' === 55);//false
variable = boolean_expression? true_value: false_value;
如果boolean_expression为true,那么返回 true_value,否则返回false_value。
有=,+=, *=,/=,-=,<<=,>>=, >>>=
//可以用来声明多个变量
var a, b, c;
//在表达式中,逗号中的最后一项是返回值
var d = (1, 2, 3, 4);
console.log(d);//4
if, do-while, while,for, break, continue, lable, switch跟其它语言类似,没啥说的。
with语句不推荐使用,就不说了。
用来枚举对象的属性。
let a = {
name: 'name',
value: 'value'
};
for (var prop in a) {
console.log(prop);
}
// name
// value
switch有点特殊,switch中可以使用任何数据类型,case中可以是常量,变量或者表达式。
switch ('hello world') {
case 'hello' + ' world':
console.log('greeting was found');
break;
default:
console.log('not found');
}
// greeting was found
语法是
function functionName(arg0, arg1, ... argN) {
statement
}
严格模式下有些限制;不要把函数或参数命名为eval或arguments。
/*
可以在函数中访问arguments变量,它是一个类数组的对象,有length属性,
表示传入了多少个参数,arguments[i]对应第i+1个参数
*/
function howManyArgs(a, b, c) {
console.log(arguments.length);
}
howManyArgs(1,2,3);//3
howManyArgs(1,2);//2
// js函数没有重载,因为函数的参数只是方便记忆和使用,
// 如果没有定义形参,可以使用arguments来访问参数
// 定义同名的函数,其实是覆盖了之前的定义,使用最后的定义
function add(a, b) {
console.log(a+b);
}
function add(a) {//覆盖了第一个函数的定义
console.log(a+100);
}
add(1,2);// 101
add(1);// 101