JavaScript语言精粹经典实例(整理篇)
数据类型
JavaScript是弱类型语言,但并不是没有类型,JavaScript可以识别下面7种不同类型的值:
基本数据类型
1.Boolean
2.Number
3.String
4.null
5.undefined
6.Symbol
Object
1.Array
2.RegExp
3.Date
4.Math
5....
可以使用typeof判断数据类型,操作符返回一个字符串,但并非返回的所有结果都符合预期
typeoffalse//"boolean" typeof.2//"number" typeofNaN//"number" typeof''//"string" typeofundefined//"undefined" typeofSymbol()//"symbol" typeofnewDate()//"object" typeof[]//"object" typeofalert//"function" typeofnull//"object" typeofnot_defined_var//"undefined"
变量
在应用程序中,使用变量来来为值命名。变量的名称称为identifiers
声明
1.使用关键字var:函数作用域
2.使用关键字let:块作用域(blockscopelocalvariable)
3.直接使用:全局作用域
varglobal_var=1; functionfn(){ varfn_var=2; if(fn_var>10){ letblock_var=3; global_var2=4; } }
只声明不赋值,变量的默认值是undefined
const关键字可以声明不可变变量,同样为块作用域。对不可变的理解在对象上的理解需要注意
constnum=1; constobj={ prop:'value' }; num=2;//UncaughtTypeError:Assignmenttoconstantvariable. obj['prop']='value2'; obj=[];//UncaughtTypeError:Assignmenttoconstantvariable.
变量提升
JavaScript中可以引用稍后声明的变量,而不会引发异,这一概念称为变量声明提升(hoisting)
console.log(a);//undefined vara=2;
等同于
vara; console.log(a); a=2;
函数
一个函数就是一个可以被外部代码调用(或者函数本身递归调用)的子程序
定义函数
1.函数声明
2.函数表达式
3.Function构造函数
4.箭头函数
functionfn(){} varfn=function(){} varfn=newFunction(arg1,arg2,...argN,funcBody) varfn=(param)=>{}
arguments
1.arguments:一个包含了传递给当前执行函数参数的类似于数组的对象
2.arguments.length:传给函数的参数的数目
3.arguments.caller:调用当前执行函数的函数
4.arguments.callee:当前正在执行的函数
functionfoo(){ returnarguments; } foo(1,2,3);//Arguments[3] //{"0":1,"1":2,"2":3}
rest
functionfoo(...args){ returnargs; } foo(1,2,3);//Array[3] //[1,2,3] functionfn(a,b,...args){ returnargs; } fn(1,2,3,4,5);//Array[3] //[3,4,5]
default
函数的参数可以在定义的时候约定默认值
functionfn(a=2,b=3){ returna+b; } fn(2,3);//5 fn(2);//5 fn();//5
对象
JavaScript中对象是可变键控集合(keyedcollections)
定义对象
1.字面量
2.构造函数
varobj={ prop:'value', fn:function(){} }; vardate=newDate();
构造函数
构造函数和普通函数并没有区别,使用new关键字调用就是构造函数,使用构造函数可以实例化一个对象
函数的返回值有两种可能
1.显式调用return返回return后表达式的求值
2.没有调用return返回undefined
functionPeople(name,age){ this.name=name; this.age=age; } varpeople=newPeople('Byron',26);
构造函数返回值
1.没有返回值
2.简单数据类型
3.对象类型
前两种情况构造函数返回构造对象的实例,实例化对象正是利用的这个特性
第三种构造函数和普通函数表现一致,返回return后表达式的结果
prototype
1.每个函数都有一个prototype的对象属性,对象内有一个constructor属性,默认指向函数本身
2.每个对象都有一个__proto__的属性,属相指向其父类型的prototype
functionPerson(name){ this.name=name; } Person.prototype.print=function(){ console.log(this.name); }; varp1=newPerson('Byron'); varp2=newPerson('Casper'); p1.print(); p2.print();
this和作用域
作用域可以通俗的理解
1.我是谁
2.我有哪些马仔
其中我是谁的回答就是this
马仔就是我的局部变量
this场景
普通函数
1.严格模式:undefined
2.非严格模式:全局对象
3.Node:global
4.浏览器:window
构造函数:对象的实例
对象方法:对象本身
call&apply
1.fn.call(context,arg1,arg2,…,argn)
2.fn.apply(context,args)
functionisNumber(obj){ returnObject.prototype.toString.call(obj)==='[objectNumber]'; }
Function.prototype.bind
bind返回一个新函数,函数的作用域为bind参数
functionfn(){ this.i=0; setInterval(function(){ console.log(this.i++); }.bind(this),500) } fn(); ()=>{}
箭头函数是ES6提供的新特性,是简写的函数表达式,拥有词法作用域和this值
functionfn(){ this.i=0; setInterval(()=>{ console.log(this.i++); },500) } fn();
继承
在JavaScript的场景,继承有两个目标,子类需要得到父类的:
1.对象的属性
2.对象的方法
functioninherits(child,parent){ var_proptotype=Object.create(parent.prototype); _proptotype.constructor=child.prototype.constructor; child.prototype=_proptotype; } functionPeople(name,age){ this.name=name; this.age=age; } People.prototype.getName=function(){ returnthis.name; } functionEnglish(name,age,language){ People.call(this,name,age); this.language=language; } inherits(English,People); English.prototype.introduce=function(){ console.log('Hi,Iam'+this.getName()); console.log('Ispeak'+this.language); } functionChinese(name,age,language){ People.call(this,name,age); this.language=language; } inherits(Chinese,People); Chinese.prototype.introduce=function(){ console.log('你好,我是'+this.getName()); console.log('我说'+this.language); } varen=newEnglish('Byron',26,'English'); varcn=newChinese('色拉油',27,'汉语'); en.introduce(); cn.introduce();
ES6class与继承
"usestrict"; classPeople{ constructor(name,age){ this.name=name; this.age=age; } getName(){ returnthis.name; } } classEnglishextendsPeople{ constructor(name,age,language){ super(name,age); this.language=language; } introduce(){ console.log('Hi,Iam'+this.getName()); console.log('Ispeak'+this.language); } } leten=newEnglish('Byron',26,'English'); en.introduce();
语法
labelstatement
loop:
for(vari=0;i<10;i++){ for(varj=0;j<5;j++){ console.log(j); if(j===1){ breakloop; } } } console.log(i);
语句与表达式
varx={a:1}; {a:1} {a:1,b:2}
立即执行函数
(function(){}()); (function(){})(); [function(){}()]; ~function(){}(); !function(){}(); +function(){}(); -function(){}(); deletefunction(){}(); typeoffunction(){}(); voidfunction(){}(); newfunction(){}(); newfunction(){}; varf=function(){}(); 1,function(){}(); 1^function(){}(); 1>function(){}();
高阶函数
高阶函数是把函数当做参数或者返回值是函数的函数
回调函数
[1,2,3,4].forEach(function(item){ console.log(item); });
闭包
闭包由两部分组成
1.函数
2.环境:函数创建时作用域内的局部变量
functionmakeCounter(init){ varinit=init||0; returnfunction(){ return++init; } } varcounter=makeCounter(10); console.log(counter()); console.log(counter());
典型错误
for(vari=0;i<doms.length;i++){ doms.eq(i).on('click',function(ev){ console.log(i); }); } for(vari=0;i<doms.length;i++){ (function(i){ doms.eq(i).on('click',function(ev){ console.log(i); }); })(i); }
惰性函数
functioneventBinderGenerator(){ if(window.addEventListener){ returnfunction(element,type,handler){ element.addEventListener(type,hanlder,false); } }else{ returnfunction(element,type,handler){ element.attachEvent('on'+type,handler.bind(element,window.event)); } } } varaddEvent=eventBinderGenerator();
柯里化
一种允许使用部分参数生成函数的方式
functionisType(type){ returnfunction(obj){ returnObject.prototype.toString.call(obj)==='[object'+type+']'; } } varisNumber=isType('Number'); console.log(isNumber(1)); console.log(isNumber('s')); varisArray=isType('Array'); console.log(isArray(1)); console.log(isArray([1,2,3])); functionf(n){ returnn*n; } functiong(n){ returnn*2; } console.log(f(g(5))); functionpipe(f,g){ returnfunction(){ returnf.call(null,g.apply(null,arguments)); } } varfn=pipe(f,g); console.log(fn(5));
尾递归
1.尾调用是指某个函数的最后一步是调用另一个函数
2.函数调用自身,称为递归
3.如果尾调用自身,就称为尾递归
递归很容易发生"栈溢出"错误(stackoverflow)
functionfactorial(n){ if(n===1)return1; returnn*factorial(n-1); } factorial(5)//120
但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误
functionfactorial(n,total){ if(n===1)returntotal; returnfactorial(n-1,n*total); } factorial(5,1)//120
柯里化减少参数
functioncurrying(fn,n){ returnfunction(m){ returnfn.call(this,m,n); }; } functiontailFactorial(n,total){ if(n===1)returntotal; returntailFactorial(n-1,n*total); } constfactorial=currying(tailFactorial,1); factorial(5)//120
反柯里化
Function.prototype.uncurry=function(){ returnthis.call.bind(this); };
push通用化
varpush=Array.prototype.push.uncurry(); vararr=[]; push(arr,1); push(arr,2); push(arr,3); console.log(arr);
以上内容是小编给大家介绍的JavaScript语言精粹经典实例(整理篇)的全部叙述,希望对大家有所帮助!