ECMAscript 6(在2015年出现),是最新的javascript标准!es5环境可以用Babel进行编译来支持es6!
第一章:数据类型
1.Number,string,boolean,undefind,null(这5个是原始类型,也叫基元类型) 和 object!
object又包括function,array,Date等等
2. 隐式转换
m - 0 把num字符串,- 0 转换成数字
num + '' 加一个空字符串,把num转换成字符串
3.等于和严格等于
=== (严格等于)
类型不同,返回false,array ≠ string
类型相同后, null = null
undefind = undefind
NaN ≠ NaN (NaN和任何都不相等,包括他本身)
new Object() ≠ new Object() (空对象之间也不严格相等,只有var之后才会严格等于);
== (等于)
类型相等,就 ===
null == undefind
number = string 1='1.0' 会进行类型转换 把Number转换成string
boolean = ? false=0, true = 1;会先把boolean转换成数字
object == string||Number 会尝试把对象转换成基本类型 new Object('hi') == 'hi';
4.包装对象
当基本类型被赋值,操作属性 等对象才有的操作,javascript会临时给基本类型转换成对象,最后输出基本类型的时候,又会销毁这个临时对象类型
var str = 'abc';
str.t = 'a';//输出a
console.log(str.t) //输出undefind
5.数据类型检测
typeof typeof 123 //Number
typeof 'aa' //string
typeof [1,2] //数组也是对象 返回object
typeof (underfind) //underfind
typeof new Object() //object
typeof NaN // Number
typeof null //object 历史原因,只需要记住
适用于基本类型及function的检测,但是遇到null会失效,可以用===(严格等于)来判断
Object.prototype.toString.apply()
Object.prototype.toString.apply([]); // object Array
Object.prototype.toString.apply(function(){}); //object Function
Object.prototype.toString.apply(new Object()); //object Object
Object.prototype.toString.apply(undefind); //object undefind
Object.prototype.toString.appyy(null); //object null
(在ie 6 7 8 null 或者undefind 会返回 object object)
适合内置对象和基本类型,遇到null和undefind会失效(ie 6 7 8会返回object Object);
instanceof obj instanceof Object(这里的obj 必须是对象 不然会返回 false 这里的Object必须是函数对象或者函数构造器,否则会返回 TypeError)
[1,2] instanceof Array //true
new Object instanceof Array //false
适合自定义对象,也能用于原声对象,在不同iframe 和 window会失效。
constructor 由于可以被改写,不太常用
duck type
第二章:对象
概述:对象中包含一系列属性,这些属性是无序的,而且每个属性都有一个字符串key和相应的value。
1. 对象的属性方法:writable , enumerable , configurable , value , get/set!
2. 创建对象的方式:
a. 对象字面量 var object = {};object.x = 1;
b. new/原形链
c. 对象创建-Object.Create
var obj = Object.create({x:1});
obj.x //1
obj.hasOwnProperty('x') //false
x in obj //true in会查找obj的原形链
3.属性操作
a.属性读写 :
var obj = {x:1,y:2}; obj.x//推荐 或者 obj['x']
b.属性删除 :
var person = {age:28,title:'life'};
delete person.age;//true
delete person['title'] //true
person.age; //undefined
delete person.age //true age已经不存在,删除也没什么错误,所以还是返回true
delete Object.prototype // false 原形的prototype的configurable为false不可配置
var globalVal = 1; delete globalVal;//false (function(){ var val = 1; return delete val;})(); // false 全局变量不可删除
c.属性检测
var cat = new Object;
cat.legs = 4;
cat.name = 'Kitty'`;
'legs' in cat; //true
'abc' in cat;//false 'abc'既不在cat上 也不在Object的prototype上
'toString' in cat; //true Object.prototype上有toString
cat.hasOwnProperty('legs'); // true
cat.hasOwnProperty('toString');//false hasWonProperty 并不会查找cat的原形链的prototype属性
cat.propertyIsEnumerable('legs'); //true 判断legs是否可枚举
cat.propertyIsEnumerable('toString'); //false
Object.defineProperty(cat,'price',{enumerable:false,value:1000}); //cat 为对象 'price'为属性 enumerable:false 不可枚举 value:1000 值为1000
cat.propertyIsEnumerable('price);//false
cat.hasOwnProperty('price'); //true
d.属性枚举
var o = {x:1,y:2,z:3};
'toString' in o;//true
o.propertyIsEunmerable('toString'); //false
var obj = Object.create(o);
obj.a = 4;
var key;
for(key in obj){
console.log(key); //a,x,y,z 用for in循环会输出原形链的内容
};
//以下是简单办法
var obj = Object.create(o);
obj.a = 4;
var key;
for(key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); //a
}
}
E. 对象属性操作的get/set方法;
//常规方法
var man = {
name : 'Bosn',
weibo : '@Bosn',
get age(){
return new Date().getFullYear() - 1988;
},
set age(val){
console.log('Age can\'t be set to' + val);
}
};
console.log(man.age);// 27 读取man.age时,会触发get方法。
man.age = 100;//当你给man.age赋值时 ,会触发man对象的set方法,输出 Age can't be set to 100
console.log(man.age); // 27 set方法没有进行值的操作
//当set/get方法与原形链
function foo(){};
Object.defineProperty(foo.prototype,'z',{get:function(){return 1;}});
var obj = new foo();
obj.z;//1
obj.z = 10;//对obj.z进行赋值,obj上没有,然后原形上有get/set方法时,会进行原形的get/set方法
obj.z;//1
//修改obj的z属性方法
Object.defineProperty(obj,'z',{value:100,configurable:true});
obj.z; //100
delete obj.z;
obj.z;//1
//另外一种情况 writable = false;
var o ={};
Object.defineProperty(o,'x',{value:1}); //为O对象 创建一个x属性,值为1,默认writable=false,configurable = false;
var obj = Object.create(o);
obj.x; // 1
obj.x = 100;
obj.x;//1 当obj上没有,x,而原形上的x的writable为false,所以就算是前面obj.x = 100,输出还是为1;
//修改obj.x的方法如下:
Object.defineProperty(obj,'x',{writable:true,value:500});
obj.x; // 500
obj.x = 1000;
obj.x;// 1000 obj的writable为true
F. 对象的属性标签
Object.getOwnPropertyDescriptor({pro : true},'pro');
//Object{value:true,writable:true,enumerable:true,configurable:true};
var person = {};
Object.defineProperty(person,'name',{
configurable:false,
writable:false,
enumerable:true,
value:'Bosn Ma'
});
person.name; //Bosn Ma
person.name = 1;
person.name;//Bosn Ma ,因为上面的writable:false
delete person.name;//false 因为上面的configurable:false
G. 对象标签
_proto_ 原形标签
//class标签
var toString = Object.prototype.toString;
function getType(o){return toString.call(o).slice(8,-1);};
getType(null); //Null
getType(1); //Number
getType(new Number(1)); //Number
getType(true); //Boolean
对象序列化
var obj = {x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj);//"{"x":1,"y":true,"Z":[1,2,3]}" 把javascript对象转换为json数据
注意:var obj = {val:undefined,a:NaN,b:Infinity,c:new Date()};
这里的值undefined会消失,NaN,Infinity会变成null,new Date()会变成utc格式。在json对象里面
//json数据转换成js对象
obj = JSON.parse('{"x":1}');
obj.x; //1
//序列化自定义
var obj = {
x:1,
y:2,
o:{
o1:1,
o2:2,
toJSON:function(){
return this.o1 + this.o2;
}
}
};
JSON.stringify(obj); // "{"x":1,"y":2,"o":3}"
第三章 数组
概述:数组是值的有序结合,每个值叫做元素,每个元素都有在数组中的位置,也就是索引。js中的数组是弱类型的,数组中可以含有不同类型的元素。数组元素甚至可以是对象或者其他数组。
数组字面量:
var arr = [1,true,null,undefined,{x:1},[1,2,3]];
var arr2 = [1,,2];//1,undefined,2
var arr3 = [,,];//undefined,undefined 会忽略最后一个逗号
第四章:函数和作用域(函数,this)
概述:函数是一块JavaScript代码,被定义一次,但可执行和调用多次。js中函数也是对象,所以函数可以像其他对象一样操作和传递,所以函数也叫函数对象。
函数一般分为三种: 函数声明(会前置) 函数表达式,new的函数构造器。
this
- 作为对象方法的函数的this
var o = {
prop:37,
f:function(){
return this.prop;
};
};
console.log(o.f()); //37 对象方法的this 会指向当前对象
----------
var o = {prop:37};
function independent(){
return this.prop; //如果直接调用函数,这里的this会指向全局window,在node里面会指向glob;
};
o.f = independent;
console.log(o.f());//37 f里面的this 会指向调用的其函数的对象
2.对象原形链上的this
var o = {
f:function(){
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 2;
console.log(p.f()); //3 用O创建一个p的原形,p调用原形上的f函数,里面的this会指向调用的对象p,1 + 2 = 3;
3.get/set方法与this
function modulus(){
return Math.sqrt(this.re * this.re + this.im * this.im); //Math.sqrt返回一个数的平方根
};
var o = {
re:1,
im:-1,
get phase(){
return Math.atan2(this.im,this.re);
};
};
Object.defineProperty(o,'modulus',{
get:modulus,enumerable:true,configurable:true
});
console.log(o.phase,o.modulus); //-0.78 1.4142 get/set方法与对象方法差不多,this会指向调用的对象,也就是这里的o;
4.构造器中的this
function MyClass(){
this.a = 37;
}
var o = new MyClass();
console.log(o.a); //37
当使用new时,MyClass函数内的this会指向MyClass的prototype,然后o的原形也是指向MyClass的prototype属性,这里的this就会指向o。ps:MyClass函数没有return 或者return 回基本类型,都是返回this。
----------
function C2(){
this.a = 37;
return {a:38};
}
o = new C2();
console.log(o.a); // 38 由于C2函数return 回的是一个对象,C2函数内的this 就会指向return 回来的这个对象 所以o.a 输出38;
5.call/apply方法与this
function add(c,d){
return this.a + this.b + c + d;
}
var o = {a:1,b:2};
add.call(o,5,6);//1+2+5+6=14;
add.apply(o,[10,11]);//1+2+10+11 = 24; call和apply 基本没什么不同,就是apply的传参是传入一个数组
function bar(){
console.log(Object.prototype.toString.call(this));
};
bar.call(7);//[Object Number]
6.bind方法与this
function f(){
return this.a;
}
var g = f.bind({a:"test"});
console.log(g()); // test
var o ={a:37,f:f,g:g};
console.log(o.f(),o.g());// 37,test
调用o.f()时,f函数会根据对象调用方法的情况,this会指向o, o.a = 37
调用o.g()时,this会指向bind绑定的对象,this指向{a:'test'};所以输出test
arguments
function foo(x,y){
console.log(x,y,this);
}
foo.call(100,1,2); //1,2,Number(100) call或者apply的第一个对象必须是对象,这里的100会转换成Number(100);
foo.apply(true,[3,4]);//3,4,Boolean
foo.apply(null); //undefined,undefined,window
foo.apply(undefined); // undefined,undefined,window
----------
function foo(x,y){
'use strict'; //严格模式下的区别
console.log(x,y,this);
}
foo.apply(null); // undefined,undefined,null
foo.apply(undefined); //undefined,undefined,undefined
bind与碎片化
function add(a,b,c){
return a + b + c;
};
var func = add.bind(null,100);
func(1,2); // 103 add的第一次bind,会把100作为参数a,bind的第一个参数可以是null 或者undefined
var func2 = func.bind(null,200); func继续bind,会把200 做为add函数的b参数,这样就形成了碎片化
func2(5); //305
bind与new
function foo(){
this.b = 100;
return this.a;
}
var func = foo.bind({a:1});
func();//1
foo的this会指向bind的参数, a:1,b:100,只是foo函数里面只有return this.a 所以输出1;
new func();
//当使用new的时候,会忽略bind(从this的这个层面),foo函数retur this.a(也就是return基本对象),
而会变成返回一个空对象,而这个空对象指向foo的prototype属性,这个空对象会因为foo.prototype的b属
性会设置成100,然后这个对象又会作为返回值返回。所以结果是{b:100};
闭包
概述:在计算机科学中,闭包(也称此法闭包或者函数闭包)是指一个函数或者函数的引用,与另一个引用环境绑定在一起,这个引用环境是一个存储该函数每个非局部变量(也叫自由变量)的表;
或者
闭包不是一般函数,他允许一个函数在立即词法作用域外调用时,仍可以访问非本地变量。
function outer(){
var localVal = 30;
return function(){
return localVal;
};
}
var func = outer();
func(); //30
实例:
document.body.innerHTML = "<div id='div1'>1</idv id='div2'>2<div></div id='div3'>3<div></div>";
for(var i = 1;i<4;i++){
(function(k){
document.getElementById('div'+k).addEventListener('click',function(){
alert(k);
});
})(i);
};
闭包-封装
(function(){
var _userId = 23495;
var _typeId = 'item';
var export = {};
function converter(userId){
return +userId;
};
export.getUserId = function(){
return converter(_userId);
};
export.getTypeId = function(){
return _typeId;
};
window.export = export;
})();
export.getUserId();//'23495'
export.getTypeId(); //'item'
export._userId; //undefined
export.typeId; //undefined
export.converter; //undefined
作用域
var a = 10; //全局
(function(){
var b = 10;
})();
console.log(a); //10
console.log(b); // undefined
作用域链
function outer(){
var i = 1;
var func = new Function("console.log(typeof i)");
func(); // undefined
}
outer();
面向对象 OOP
Student.prototype.x = 101;
Student.prototype = {y:2};
bosn.y; //undefined
bosn.x = 101;
var nun = new Student('Nun',3,'class LOL');
nun.x; //undefined
nun.y = 2;
修改prototype的值,并不能改变已经创建的实例,只会对后来创建的实例产生影响
instanceof
[1,2] instanceof Array === true;
new Object instanceof Array === false;
[1,2] instanceof Object === true;
实现继承的方式
function Person(){}
function Student(){}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Person;
ES5后实现方法
if(!Object.create){
Object.create = function(proto){
function F(){}
F.prototype = proto;
return new F;
}
}