回到了本身的家乡,期待中有感受到了不少的陌生,一个有“故事”的环境中,你我是否“孤独”!javascript
在我看来function共有三种类型,做为对象使用,处理业务以及穿件object的实例对象。跟这三种用法相对应的有三种子类型,分别是对象的属性、变量(包括参数)和建立出来的object类型实例对象的属性。这三种子类是相互独立的,并且也很容易区分。可是,咱们刚刚接触的时候很容易混淆。java
这种状况下,function对象的子类型就是对象本身的属性,这时经过操做符“.”(或者方括号操做符)使用,示例以下:闭包
function book(){}
book.price=999;
book["getPrice"]=function(){
return this.price;
}
console.log(book.getPrice()); //输出结果:999
复制代码
我不多碰到function来做为object类型的对象来使用。函数
这种状况下,function的子类型就是本身定义的局部变量(包括参数),这时的变量实在方法被调用时经过变量做用域链来管理的。 关于变量我以前的文档中有涉及到,这里就不过多的说明了。测试
这种状况下,对应的子类型是使用function建立实例对象的属性(很经常使用),主要包括在function中经过this添加属性,以及建立完成以后实例对象本身添加的属性。另外,还能够调用function的prototype属性对象所包含的属性,示例以下:ui
function Car(color,displacement){
this.color = color;
this.displacement = displacement;
}
Car.prototype.logMessage = function(){
console.log(this.color+","+this.displacement);
};
var car = new Car("yellow","2.4T");//看看是否是相似构造函数?哈哈
复制代码
这个例子中建立的car对象就包含有color和displacement两个属性,并且还能够调用Car.prototype的logMessage方法。固然,建立完以后还可使用点操做符给建立的car对象添加或者修改属性,也可使用delete删除其中的属性,示例以下:this
function Car(color,displacement){
this.color = color;
this.displacement = displacement;
}
//全部建立出来的car都有该方法
Car.prototype.logMessage = function(){
console.log(this.color+","+this.displacement);
};
var car = new Car("yellow","2.4T");//看看是否是相似构造函数?哈哈
//给car对象添加属性
car.logColor = function(){
console.log(this.color);
};
//完成调用测试
car.logColor();//输出结果: yellow
car.color = "red";
car.logColor();//输出结果:red
delete car.color;//删除属性
car.logColor();//输出结果:undefined
复制代码
代码分析:spa
在建立完car对象以后,又给它添加了logColor的方法,能够打印car的color属性。添加完logColor方法后直接调用就能够打印出car原来的color属性值(yellow)。而后,将其修改成red,在打印出了red。最后,使用delete删除car的color的属性,这时在调用logColor方法会打印出undefinedprototype
其实跟个人注释说明一致!!!code
function的三种子类型是相互独立的,他们只能在本身所对应的环境中使用而不能相互调用,示例以下:
function log(msg){//第二种业务处理
console.log(msg);
}
function Bird(){
var name = "kitty";
this.type = "pigeon";
this.getName = function(){
return this.name;//建立的对象没有name属性
}
}
Bird.color = "white";//第一种object类型的对象
Bird.getType = function(){//第一种object类型的对象
return this.type;
};
Bird.prototype.getColor = function(){//第三种建立对象
return this.color;
}
var bird = new Bird();
log(bird.getColor());// undefined
log(bird.getName()); // undefined
log(bird.getType()); // undefined
复制代码
Bird 做为对象时包含 color 和 getType 两个属性,做为处理业务的函数是包含一个名为name的局部变量,建立的实例对象bird具备type和getName两个属性,并且还能够调用Bird.prototype的getColor属性,getColor也能够看做bird的属性。
用 法 | 子 类 型 |
---|---|
对象(Bird) | color 、getType |
处理业务(Bird方法) | name |
建立实例对象(bird) | type、getName、(getColor) |
每种用法中所定义的方法只能调用相对应所对应的属性,而不能交叉调用,从对应关系中能够看出,getName、getColor和getType三个方法中没法获取到值,你们再仔细分析一下!
另外,getName和getColor是bird的属性方法,getType是Bird的属性方法,若是用Bird对象调用getName或getColor方法或者使用bird对象调用getType方法都会抛出找不到的错误。
三种子类型不能够相互进行调用以外,还有一种状况也很是重要:那就是对象的属性并无继承的关系。
function obj(){}
obj.v=1;
obj.func = {
logV : function(){
console.log(this.v);
}
}
obj.func.logV();
复制代码
代码分析:
这个例子中的obj是做为对象使用的,obj是有一个属性v和一个对象属性func,func对象中又有一个logV方法,logV方法用于打印对象的v属性。这里须要特别注意:
logV方法打印的是func对象的v属性,可是func对象中并无v属性,因此最后结果是undefined。
这个例子中,虽然obj对象中包含v属性,可是因为属性不能够继承,因此obj的func属性对象中的方法不可使用obj中的属性v.
请你们必定要记住,而且不要和prototype的继承以及变量做用域链相混淆
三种子类型原本是相互独立、各有各的使用环境的,可是,有一些状况下须要操做不属于本身所对应环境的子类型,这时就须要使用一些技巧来实现了。
约定以下
op | v | ip | |
---|---|---|---|
O | 直接调用 | 在函数中关联到O的属性 | 不可调用 |
F | 使用O调用 | 直接调用 | 不可调用 |
I | 使用O调用 | 在函数中关联到I的属性 | 直接调用 |
纵向表头表示function的不一样用法
横向表头表示三种类型,表格的主体表示在function相应用法中调用各类子类的方法。
由于function建立的实例对象在建立以前还不存在,因此function做为方法(F)和做为对象(O)使用时没法调用function建立的实例对象的属性(ip)。调用参数能够在函数中将变量关联到相应的属性,调用function做为对象(O)时的属性能够直接使用 function 对象来调用
function log(msg){
console.log(msg);
}
function Bird(){
//私有属性
var name = "kitty";
var type = "pigeon";
//将局部变量name关联到新建立的对象的getName,setName属性方法
//闭包可使用局部变量
//公有属性
this.getName = function(){
return name;
}
this.setName = function(n){
name = n;
}
//将局部变量type关联到Bird对象getType属性方法
//静态属性
Bird.type = function(){
return type;
}
//在业务处理中调用Bird对象的color属性
log(Bird.color);//输出结果: white,F调用op
}
Bird.color = "white";// 表明 O
//在建立出的实例对象中调用Bird对象的color属性
Bird.prototype.getColor = function(){//I
return Bird.color;//OP
}
var bird = new Bird(); // 建立实例 I
log(bird.getColor()); // 输出结果:white , I 调用 op
log(bird.getName());// 输出结果:kitty , I 调用 v 局部变量
log(Bird.getType());// 输出结果:pigeon , O 调用 v 局部变量
bird.setName("petter"); // I 调用 v
log(bird.getName());// 输出结果:petter , I 调用 v 局部变量
复制代码
好好分析上述的代码,很是经典的,了解三种子类型的不一样环境用法中交叉调用的方法
上面的示例中咱们涉及到了公有属性、私有属性和静态属性的说明,因为JS并非基本类而是基于对象的语言,所以JS自己并无这些概念。