写在前面:
这篇大部分内容是《js高程》第6-7章的代码笔记,记在网上也是方便自己以后随时随地可以回看。
笔记是按个人情况来记的,所以可能不是全部的内容都特别详细。
直接上代码,详见代码注释。
下面的代码是在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(){})加上括号转换成函数表达式
var name='Mike';
(function(){
if(typeof name=='string'){
var name='Jack';
console.log('hello '+name);
}else{
console.log('goodbye '+name);
}
})();
//在这个匿名函数的作用域里,声明提前,name是已经声明的,覆盖个外面的全局变量,但没有赋值,
//所以输出'goodbye undefined'
//如果将'string'改成'undefined',就会输出'hello Jack'
//静态私有变量
(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('------------------------------------');