直接上代码,详见代码注释。
下面的代码是在sublime text3上编辑在nodejs上运行过的。
【创建对象】
//创建对象 //组合使用构造函数模式(定义实例属性)和原型模式(定义方法、constructor) function Person_1(name,age,job){ this.name=name; this.age=age; this.job=job; this.friends=['Shelby','Court']; } Person_1.prototype={ sayName:function(){ console.log(this.name); } } Object.defineProperty(Person_1.prototype,'constructor',{ enumerable:false, value:Person_1 }); var person=new Person_1('Nick',20,'Software Engineer'); person.sayName();//Nick //动态原型模式(所有信息封装在构造函数中) function Person_2(name,age,job){ this.name=name; this.age=age; this.job=job; this.friends=['Shelby','Court']; //if这段代码只有在初次调用构造函数时才会执行 if(typeof this.sayName !='function'){ Person_2.prototype.sayName=function(){console.log(this.name);}; } } var person=new Person_2('Nick',20,'Software Engineer'); person.sayName();//Nick console.log('------------------------------------');
【继承】
//继承 //实现继承的本质是重写原型对象,代之以一个新类型的实例 //确定原型和实例的关系的方法:1、instanceof操作符 2、isPrototypeOf() function SuperType_1(){ this.superproterty=true; } SuperType_1.prototype.getSuperValue=function(){ return this.superproterty; } function SubType_1(){ this.subproperty=false; } //继承了SuperType_1 SubType_1.prototype=new SuperType_1(); SubType_1.prototype.getSubValue=function(){ return this.subproperty; } var instance=new SubType_1(); console.log(instance.getSuperValue());//true console.log(instance instanceof Object);//true console.log(instance instanceof SuperType_1);//true console.log(instance instanceof SubType_1);//true console.log(Object.prototype.isPrototypeOf(instance));//true console.log(SubType_1.prototype.isPrototypeOf(instance));//true console.log(SuperType_1.prototype.isPrototypeOf(instance));//true console.log('------------------------------------');
//借用构造函数/伪造对象/经典继承 //在子类构造函数内部调用超类构造函数,使用apply()、call() //即使超类中有引用类型的属性,也会在子类创建一个副本 function SuperType_2(){ this.colors=['red','blue','green']; } function SubType_2(){ //继承了SuperType_2 SuperType_2.call(this); } var instance1=new SubType_2(); instance1.colors.push('black'); console.log(instance1.colors);//[ 'red', 'blue', 'green', 'black' ] var instance2=new SubType_2(); console.log(instance2.colors);//[ 'red', 'blue', 'green' ] console.log(instance1 instanceof Object);//true console.log(instance1 instanceof SuperType_2);//false console.log(instance1 instanceof SubType_2);//true console.log(Object.prototype.isPrototypeOf(instance1));//true console.log(SubType_2.prototype.isPrototypeOf(instance1));//true console.log(SuperType_2.prototype.isPrototypeOf(instance1));//false console.log('------------------------------------');
//组合继承/伪经典继承 //使用原型链实现对原型属性和方法的继承 //通过构造函数实现对实例属性的继承 //两次调用SuperType_3() function SuperType_3(name){ this.name=name; this.colors=['red','blue','green']; } SuperType_3.prototype.sayName=function(){ console.log(this.name); }; function SubType_3(name,age){ //继承属性 SuperType_3.call(this,name);//二次调用SuperType_3() this.age=age; } //继承方法 SubType_3.prototype=new SuperType_3();//一次调用SuperType_3() SubType_3.prototype.constructor=SubType_3; SubType_3.prototype.sayAge=function(){ console.log(this.age); }; var instance3=new SubType_3('Nicholas',29); instance3.colors.push('brown'); console.log(instance3.colors);//[ 'red', 'blue', 'green', 'brown' ] instance3.sayAge();//29 instance3.sayName();//Nicholas var instance4=new SubType_3('Greg',27); console.log(instance4.colors);//[ 'red', 'blue', 'green' ] instance4.sayName();//Greg instance4.sayAge();//27 console.log(instance4 instanceof Object);//true console.log(instance4 instanceof SuperType_3);//true console.log(instance4 instanceof SubType_3);//true console.log(Object.prototype.isPrototypeOf(instance4));//true console.log(SubType_3.prototype.isPrototypeOf(instance4));//true console.log(SuperType_3.prototype.isPrototypeOf(instance4));//true console.log('------------------------------------');
//原型继承 //ECMAScript5增加了Object.create()方法,接收两个参数(用于创建副本的基本对象,可选的为新对象定义额外属性的对象) //IE 9+、Firefox 4+、Safari 5+、Opera 12+、Chrome //只想让一个对象与另一个对象保持类似的情况下,原型继承可行 var person={ name:'Nicholas', friends:['a','b','c'] }; var aperson=Object.create(person); aperson.name='Greg'; aperson.friends.push('d'); var anotherperson=Object.create(person,{name:{value:'ccc'}}); console.log(person.friends);//[ 'a', 'b', 'c', 'd' ] console.log(anotherperson.name);//ccc console.log(anotherperson.friends);//[ 'a', 'b', 'c', 'd' ] console.log('------------------------------------');
//寄生式继承 //任何能够返回新对象的函数都适用 //为对象添加函数会因为不能做到函数复用而降低效率 function object(o){ function F(){} F.prototype=o; //原型指向o,所以对其原型的任何更改也会反映到o上 return new F(); } function createAnother(originaobj){ var clone=object(originaobj); clone.sayHi=function(){ console.log('hi'); }; return clone; } var person={ name:'Nicholas', friends:['a','b','c'] }; var yetAnotherPerson=createAnother(person); yetAnotherPerson.sayHi();//hi console.log('------------------------------------');
//寄生组合式继承 //解决两次调用的问题 //引用类型最理想的继承范式 function inheritPrototype(SubType,SuperType){ var prototype=Object(SuperType.prototype);//创建超类原型副本 prototype.constructor=SubType; SubType.prototype=prototype;//代替了前面的第一次调用SuperType() } function SuperType(name){ this.name=name; this.colors=['red','blue','green']; } SuperType.prototype.sayName=function(){ console.log(this.name); }; function SubType(name,age){ //继承属性 SuperType.call(this,name);//二次调用SuperType() this.age=age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge=function(){ console.log(this.age); } var instance5=new SubType('Nicholas',29); instance5.colors.push('brown'); console.log(instance5.colors);//[ 'red', 'blue', 'green', 'brown' ] instance5.sayAge();//29 instance5.sayName();//Nicholas var instance6=new SubType('Greg',27); console.log(instance6.colors);//[ 'red', 'blue', 'green' ] instance6.sayName();//Greg instance6.sayAge();//27 console.log(instance6 instanceof Object);//true console.log(instance6 instanceof SuperType);//true console.log(instance6 instanceof SubType);//true console.log(Object.prototype.isPrototypeOf(instance6));//true console.log(SubType.prototype.isPrototypeOf(instance6));//true console.log(SuperType.prototype.isPrototypeOf(instance6));//true console.log('------------------------------------');
【js中实现块级作用域】
//ECMAScript中不存在块级作用域 var count=10; for (var i = 0; i < count; i++) { console.log(i); }//循环输出0-9 console.log(i);//仍然可以访问到i为10 if(true){ var c=1; } console.log(c);//可以访问到if语句内定义的c为1 function add(num1,num2){ var sum =num1+num2; return sum; } var result=add(10,20); //console.log(sum);会报错,找不到sum var color='blue'; function getColor(){ var color='red'; return color; } console.log(getColor());//red console.log(color);//blue //匿名函数可以用来模仿块级作用域 (function(){ var count=10; for (var j = 0; j < count; j++) { console.log(j); } })(); //console.log(j);//j is not defined //function(){}();会报错 //因为js将function关键字当做函数声明的开始,函数声明后不能跟() //所以要给(function(){})加上括号转换成函数表达式【js函数私有变量】
//静态私有变量 (function(){ //私有变量和方法 var privateVariable=''; function privateFunction(){ return false; } //构造函数 //创建一个全局变量 Person_3=function(value){ privateVariable=value; }; Person_3.prototype.getValue=function(){ return privateVariable; } Person_3.prototype.setValue=function(value){ privateVariable=value; } })(); var a=new Person_3('Nick'); console.log(a.getValue());//Nick a.setValue('Greg'); console.log(a.getValue()); //Greg var b=new Person_3('Mike'); console.log(b.getValue());//Mike console.log(a.getValue());//Mike //这种方式创建静态私有变量会因为使用原型而增进代码复印,但是每个实例都是共享私有变量和函数的 console.log('------------------------------------');
//模块模式 //单例:只有一个实例的对象 //如果必须创建一个对象并以某些数据进行初始化,同时公开访问私有变量的接口 //以这种模式创建的每个单例都是Object(以函数返回的字面量形式创建的Object实例) var application=function(){ var components=new Array(); //初始化,向数组推进一个实例对象 components.push(new Object()); return{ getComponetCount:function(){ return components.length; }, registerComponet:function(component){ if(typeof component=='object'){ components.push(component); } } }; }(); //增强的模块模式 //适合那些单例必须是某种类型的实例 var application=function(){ var privateVariable=10; function privateFunc(){ return true; } var returnobj=new String(); returnobj.publicProperty=false; returnobj.publicMethod=function(){ privateVariable++; return privateFunc(); }; return returnobj; }(); console.log('------------------------------------');