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语言精粹经典实例(整理篇)的全部叙述,希望对大家有所帮助!