虽然很早就接触js了,但是一直以来都学得不好,只有半桶水,基本只够简单应用。复杂的什么例如写js控件,修改js库源码就无能为力了。虽然不是什么前端工程师,但是经常用到,所以还是学好点吧。。。
对一些概念不清楚,写函数的时候也只是非常小心,然而还是有问题,于是就调试来调试去,效率非常低。这几天有点空闲。写了测试例子,一下子清楚多了。
this 的含义
a . 在js文件的最顶层 直接调用时:
//在js文件的最顶层
//alert(this);//[object Window] 为此“全局变量”window,
var thisTest=function asYouLike(x,y) {
//alert(userManager.bbb);
this.ma = x;// 相当于给Window增加属性---- 但这是不会成功的,因为Window属性只读,不可写
this.mb = "MA";
alert("thisTest call by globe object: this = "+this);//this 为调用modify函数的对象:[object Window]---为什么不是button?这是js的实现机制决定的
alert("this.ma = "+this.ma);// 当使用new操作符的时候,this指向新建的对象!否则。。。因为之前window没定义名为ma的变量,所以undefined
alert("this.mb = "+this.mb);//undefined
alert("this.mc = "+this.mc);//undefined
}
thisTest();
b. 当把thisTest当做一个类( new+ 函数名+() )时:this所表示的意思会不同
// 几乎同样的代码
var thisTest=function asYouLike(x,y) {
this.ma = x;
this.mb = "MA";
alert("thisTest call by a class object: this = "+this);//
alert("this.ma = "+this.ma);// 当使用new操作符的时候,this指向新建的对象!==== undefined 因为没有传入x
alert("this.mb = "+this.mb);//"MA"
alert("this.mc = "+this.mc);//undefined 因为它没定义
}
var tt = new thisTest();
函数
//可以这么调用
var testFunc = function(x,y,z) {
this.name = x;
this.age = y;
testvar = z;
alert("Hello boy!");
alert("this:"+this+" x:"+x+" y:"+y+" z:"+z);
}
testFunc();
alert(testFunc);//
//也可以简单直接的这么调用:在这种情况下,testFunc为匿名函数返回值;匿名函数只能被调用一次
var testFunc2 = function(x,y,z) {
this.name = x;
this.age = y;
testvar = z;
alert("Hello boy!");
alert("this:"+this+" x:"+x+" y:"+y+" z:"+z);
}();
alert(testFunc2);//undefined
函数中变量的用法--作用域、读取的方式
//函数中变量的用法--作用域、读取的方式
var fa = " global var fa";
var fb = " global var fb";
var func = function () {
var fa = 11;
var ff = function(){
alert(fa);//原型链方式读取:首先从当前函数func中读取,找不到则..最后从全局对象中读取
alert(this.fa);//注意this在这里起的作用,他指向全局对象,所以直接从全局对象读取
alert(this.fb);
}
ff();
}
//func.ff();//TypeError: f.ff is not a function
func();
对象/类
//对象/类
//函数 ------ 其实又可当做对象的构造函数
var Person = function(name,age){
this.name = name;
this.age = age;
this.birthday = new Date();
this.toString = function (){
return "Person:name="+this.name+"/age="+this.age;
};
}
var person = new Person("lk",26);
alert(person.age);
var globeFunc = function(x,y,z) {
this.name = x;// 此处悄然改变了this(调用者) 的name值!!!
this.mc = "MMCC";
testvar = z;
alert("this:"+this+" x:"+x+" y:"+y+" z:"+z);//this:Person:name=1/age=26 x:1 y:2 z:undefined
}
globeFunc.call(person,1,2);
//小结: 函数中this跟调用环境息息相关,谁调用了这个函数,this就是谁
//小结: 对象中方法的 this ? 一般情况下就是所属的对象,但是,如果用apply/call来调用呢?
如果使用函数的call、apply来调用函数,则函数里面this的为传入的this参数,此时需要特别注意! 否则引起错误!!!
闭包:
闭包是一个比较难理解的概念,特别是对应初学者,难以真正理解,我曾经试着去理解,找了很多资料,看了很多文档,却对这个概念依然模糊,说不清道不明——当然一旦真正理解,则发现很简单了,像我现在这样;———— 所以说有些东西还是得自己亲自动手,做些小实验。所谓百读不如一练。
//闭包
//非闭包的情况
var Car = function(speed,num,miles){
var speed = speed;
return{
run:function(){
alert("running");
},
start:function(){
alert("start");
},
stop:function(){
alert("stop");
}
}
}
//Car.run();// Car.run is not a function -- 此时Car还不是一个对象
var car = new Car();
car.run();//car还只是一个对象,当然可以这么调用
alert(car.speed);// undefined
//无法访问闭包的属性,因为闭包的属性相当于被限制为private了
//speed 并不属于调用者的属性,此时可以当做闭包的属性了
//闭包的情况
var Dog = function(name,age,height){
var name = name;
return{
bart:function(){
alert("wong! wong! wong!!!");
},
eat:function(){
alert("eat");
},
sleep:function(){
alert("sleep");
}
}
}()
Dog.bart();// 此时Dog已经是一个对象 ---- 建立一个函数,然后执行它,返回return语句后面的对象!
// 所以说闭包实现的关键是
1 创建一个函数并立即执行它,使用()运算符
2 函数中的return语句中返回一个对象--- 否则函数值就是undefined
——————
// 要立即,return 返回{} 就是一个对象!—— 其实稍微想想也就知道,只是一直就没这么想过。。。
// 否则如果没有return,建立一个函数,然后执行它 --- 返回undefined
var Man = function(name,age){
this.name = name;
this.age = age;
this.mc = "MMCC";
this.speak = function (){
alert("Man:name="+this.name+"/age="+this.age);
};
}();
//Man.speak();// Man is undefined--- 这种方式却不行
var Woman = function(name,age){
this.name = name;
this.age = age;
this.mc = "MMCC";
this.speak = function (){
alert("Woman:name="+this.name+"/age="+this.age);
};
return{
run:function(){
alert("a woman is running");
}
}
}();
//Woman.run();// 现在又可行了!
//Woman.speak();//Man.speak is not a function 现在报这个错了,不是Woman is undefined
函数的嵌套
// 函数的嵌套
var Nest = function(name,age){
this.name = name;
this.age = age;// 不能写成 age = age;?这当然是不行的
this.mc = "MMCC";
var th = this;
this.speak = function (){
//alert(th);[Object]
alert(this);// 此处的this 指的是new出来的Nest对象
alert("Nest:name="+this.name+"/age="+this.th);
th.speakAlout = function (){// 如果不加this, th 从哪里获取呢?从当前对象,找不到就是全局对象
alert("a Nest is running");
}
obj.objFunc = function (){
alert("==objFunc==");
}
// th.speak.speakAlout = function (){// 如果不加this, th 从哪里获取呢?
// alert("a Nest is speakAlout");
// }
nestFunction = function (){//这样的嵌套函数是怎么调用的呢??
alert("a Nest function is running/this is:"+this);//此时的this为[object Window] ?怪怪的
}
//nestFunction();//这样调用
this.toString = function (){
return "next.speak";
}
};
this.toString = function (){
return "next.object";
}
var fasf = function() {//可以写这种函数/属性,但实际上,它是private的,外面无法调用
alert(1231312);
}
fasf();
// return{
// run:function(){
// alert("a woman is running");
// }
// }
};
var nest = new Nest("lk","123");//TypeError: Nest is not a constructor
nest.speak();// 因为speakAlout是在speak定义的,所以要先执行speak(),才能找到speakAlout
nest.speakAlout();
alert("this.nestFunction=="+this.nestFunction);// 在nest.speak()之后nestFunction已经变成了一个全局函数!
alert(nest.speak.speakAlout);//undefined 否则,直接显示函数内容
nest.fasf();//nest.fasf is not a function
nest.speak.speakAlout();//TypeError: nest.speak.speakAlout is not a function
注意:在嵌套的函数里面,this总是对应window(稍微有点疑问)
//闭包中嵌套呢?(闭包的-closure)
var closure_nest = function(name,age){
var f = function() {//可以写这种函数/属性,但实际上,它是private的,外面无法调用
alert("im a private function ! ");
var f_nest = function() {//可以写这种函数/属性,但实际上,它是private nest的,外面更加无法调用
alert("im a private nest function ! ");
}
this.f_nest_g = function() {//可以写这种函数/属性,但实际上,它是private nest的,外面更加无法调用
alert("im NOT a private nest function !im globe ");
}
}
//alert(this);// [object Window]
return {
ff:function() {//可以写这种函数/属性,但实际上,它是private的,外面无法调用
//alert("im a private function ! ");
ff_nest = function() {//可以写这种函数/属性,但实际上,它是private nest的,外面更加无法调用
alert("im a private nest function ! ");
}
this.ff_nest_g = function() {//可以写这种函数/属性,它是属于的return返回的对象的,通过闭包方式调用
alert("im NOT a private nest function !im closure ");
ff_nest_nest = function() {//可以写这种函数/属性,似乎可以永远继续嵌套!
// alert("im a private nest nest function ! this aaa:"+this);//此处的this对应window !
ffasf = function() {
alert(987923233+""+this);// N里面嵌套,此处永远的this对应window
}();
}
ff_nest_nest();
}
this.toString = function () {
return " closure_nest ff this.toString ";
}
toString = function () {// 相当于重写了 window 的toString 函数
return " closure_nest ff nested toString 相当于window的toString !";
}
wirld = function () {
ff_nest123 = function() {
alert("im a private nest nest function ! ");
alert(this);// 此处的this对应window !
// this.fffff();
}
ff_nest123();
return " closure_nest ff nested toString ";
}
fffff = function(){
alert(" fffff ! ");
}
wirld();
// ff_nest();
// alert(this);// 此处的this 又是不同含义!// 调用this.toString
}
}
// return {}后面的语句都不会执行
alert(4444);
ff_nest();
toString = function () {
return (" closure_nest ");
}
}();
//ff_nest_g();// ReferenceError: ff_nest_g is not defined
//closure_nest.ff_nest();// undefined
closure_nest.ff();
closure_nest.ff_nest_g();//在ff之后,也能正常调用