typeof操作符获取对象的类型
typeof 123; // 'number' typeof NaN; // 'number' typeof 'str'; // 'string'
不要使用new Number()、new Boolean()、new String()
用parseInt()或parseFloat()来转换任意类型到number;
用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
判断Array要使用Array.isArray(arr);
判断null请使用myVar === null;
判断某个全局变量是否存在用typeof window.myVar === 'undefined';
函数内部判断某个变量是否存在用typeof myVar === 'undefined'。
number对象调用toString()报SyntaxError:
123.toString(); // SyntaxError 123..toString(); // '123', 注意是两个点! (123).toString(); // '123'
Date对象用来表示日期和时间。
var now = new Date();
获取系统当前时间
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST) now.getFullYear(); // 2015, 年份 now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月 now.getDate(); // 24, 表示24号 now.getDay(); // 3, 表示星期三 now.getHours(); // 19, 24小时制 now.getMinutes(); // 49, 分钟 now.getSeconds(); // 22, 秒 now.getMilliseconds(); // 875, 毫秒数 now.getTime(); // 1435146562875, Date.now() //获取时间戳 以number形式表示的时间戳
创建一个指定日期和时间的Date对象
var d = new Date(2015, 5, 19, 20, 15, 30, 123);
JavaScript的月份范围用整数表示是0~11,0表示一月,1表示二月
var d = Date.parse('2015-06-24T19:49:22.875+08:00');
返回的不是Date对象,而是一个时间戳
时间戳转换为一个Date
var d = new Date(1435146562875); d; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
创建一个正则表达式
var re1 = /ABC\-001/; // 直接通过/正则表达式/写出来 var re2 = new RegExp('ABC\\-001');
匹配字符串
re1.test('010-1234x'); // false
切分字符串
'a b c'.split(/\s+/); // ['a', 'b', 'c'] 'a,b, c d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
分组
()表示的就是要提取的分组(Group)
var re = /^(\d{3})-(\d{3,8})$/; re.exec('010-12345'); // ['010-12345', '010', '12345'] re.exec('010 12345'); // null
贪婪匹配
正则匹配默认是贪婪匹配
必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,
加个?就可以让\d+采用非贪婪匹配:
全局搜索
JavaScript的正则表达式还有几个特殊的标志,最常用的是g,表示全局匹配:
var r1 = /test/g; // 等价于: var r2 = new RegExp('test', 'g');
全局匹配可以多次执行exec()方法来搜索一个匹配的字符串。当我们指定g标志后,每次运行exec(),正则表达式本身会var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g; // 使用全局匹配: re.exec(s); // ['JavaScript'] re.lastIndex; // 10 re.exec(s); // ['VBScript'] re.lastIndex; // 20 re.exec(s); // ['JScript'] re.lastIndex; // 29 re.exec(s); // ['ECMAScript'] re.lastIndex; // 44 re.exec(s); // null,直到结束仍没有匹配到
i标志,表示忽略大小写,
m标志,表示执行多行匹配。
概念
JSON是JavaScript Object Notation的缩写,它是一种数据交换格式。
数据类型
number:和JavaScript的number完全一致; boolean:就是JavaScript的true或false; string:就是JavaScript的string; null:就是JavaScript的null; array:就是JavaScript的Array表示方式——[]; object:就是JavaScript的{ ... }表示方式。
JSON还定死了字符集必须是UTF-8
JSON的字符串规定必须用双引号""
Object的键也必须用双引号""
序列化
var xiaoming = { name: '小明', age: 14, gender: true, height: 1.65, grade: null, 'middle-school': '\"W3C\" Middle School', skills: ['JavaScript', 'Java', 'Python', 'Lisp'] }; JSON.stringify(xiaoming); // '{"name":"小明","age":14,"gender":true,"height":1.65,"grade":null,"middle-school":"\"W3C\" Middle School","skills":["JavaScript","Java","Python","Lisp"]}'
要输出得好看一些,可以加上参数,按缩进输出:
JSON.stringify(xiaoming, null, ' ');
第二个参数用于控制如何筛选对象的键值
如果我们只想输出指定的属性,可以传入Array:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
还可以传入一个函数,这样对象的每个键值对都会被函数先处理:
精确控制如何序列化
定义一个toJSON()的方法,直接返回JSON应该序列化的数据:
var xiaoming = { name: '小明', age: 14, gender: true, height: 1.65, grade: null, 'middle-school': '\"W3C\" Middle School', skills: ['JavaScript', 'Java', 'Python', 'Lisp'], toJSON: function () { return { // 只输出name和age,并且改变了key: 'Name': this.name, 'Age': this.age }; } }; JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
反序列化
JSON.parse()
JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
可以接收一个函数,用来转换解析出的属性:
JSON.parse('{"name":"小明","age":14}', function (key, value) { // 把number * 2: if (key === 'name') { return value + '同学'; } return value; }); // Object {name: '小明同学', age: 14}
面向对象的两个基本概念:
类:类是对象的类型模板,
实例:实例是根据类创建的对象
Object.create()方法可以传入一个原型对象,并创建一个基于该原型的新对象,
// 原型对象: var Student = { name: 'Robot', height: 1.2, run: function () { console.log(this.name + ' is running...'); } }; function createStudent(name) { // 基于Student原型创建一个新对象: var s = Object.create(Student); // 初始化新对象: s.name = name; return s; } var xiaoming = createStudent('小明'); xiaoming.run(); // 小明 is running... xiaoming.__proto__ === Student; // true
概念
JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined。
ex
创建一个Array对象:
var arr = [1, 2, 3];
其原型链是:
arr ----> Array.prototype ----> Object.prototype ----> null
Array.prototype定义了indexOf()、shift()等方法,因此你可以在所有的Array对象上直接调用这些方法。
函数也是一个对象,它的原型链是:
foo ----> Function.prototype ----> Object.prototype ----> null
构造函数
定义一个构造函数
function Student(name) { this.name = name; this.hello = function () { alert('Hello, ' + this.name + '!'); } }
用关键字new来调用这个函数,并返回一个对象
var xiaoming = new Student('小明'); xiaoming.name; // '小明' xiaoming.hello(); // Hello, 小明!
注意:如果不写new,这就是一个普通函数,它返回undefined。但是,如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this,也就是说,不需要在最后写return this;。
原型链是:
xiaoming ↘ xiaohong -→ Student.prototype ----> Object.prototype ----> null xiaojun ↗
注意:为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这样,一些语法检查工具如jslint将可以帮你检测到漏写的new。
可以编写一个createStudent()函数,在内部封装所有的new操作。
//构造函数
function Student(props) { this.name = props.name || '匿名'; // 默认值为'匿名' this.grade = props.grade || 1; // 默认值为1 }
//共享方法
Student.prototype.hello = function () { alert('Hello, ' + this.name + '!'); };
//封装 new操作
function createStudent(props) { return new Student(props || {}) }
在大部分情况下,可以使用
Child.prototype = new Parent();
ES6开始引入calss
ex:
class Student { //构造函数 constructor(name) { this.name = name; } //方法 hello() { alert('Hello, ' + this.name + '!'); } } var xiaoming = new Student('小明'); xiaoming.hello(); class继承 class PrimaryStudent extends Student { constructor(name, grade) { super(name); // 记得用super调用父类的构造方法! this.grade = grade; } myGrade() { alert('I am at grade ' + this.grade); } }