JS面向对象
object 是javascript 父对象
function f(){ //自定义函数 } alert(f.prototype); //函数原型是object对象 alert(f.prototype instanceof object); //true
闭包 全局变量在函数内部可以访问
function a(){ var i = 0; function b(){ alert(++i); } return b; } var c = a(); c(); //1
闭包的优缺点
优点: 有利于封装,可以访问局部变量
缺点: 内存占用浪费严重,内存泄漏
function f1(){ var n = 999; nadd = function(){ n = n+1; } function f2(){ alert(n); } return f2; } var rs =f1(); rs();// 999 nadd(); // --->执行了 rs();// 1000
案例:
输出:11/12
闭包的原理是,把局部函数赋值给全局变量,由于全局变量在代码执行的过程中是不会销毁的,所以它用到的值即局部函数不会销毁。而局部函数中使用到的变量也就保存在内存中了。
var func=test()执行之后 ,func实际的值是subtest函数。当局部函数subtest赋值给了全局变量func后,内部用到的变量n保存在内存中。n的默认值是10,func()第一次调用,执行subtest函数,n自加1,弹出n的值是11。func()第二次调用,n自加1,弹出的值为12
闭包实现点击li显示点击了哪个
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>2-1</title> <style> /*补充代码*/ li{ cursor:pointer; } </style> </head> <body> <ul> <li>选项1</li> <li>选项2</li> </ul> <!-- 补充代码 --> <script> var li=document.getelementsbytagname("li"); for(var i=0,len=li.length;i<len;i++){ (function(i){ // 补充代码 li[i].onclick=function(){ alert(i); } })(i) } </script> </body> </html>
对象的声明:
字面式=json方式
var person = { name:"zhangsan", age:26, sex:"man", eat:function(fds){ alert("我在吃"+fds); }, play:function(ga){ alert("我在玩"+ga); } } alert(person.age); person.eat("面条"); alert(person instanceof object);
object方式
var box = new object(); box.name = "zhangsan"; box.age = 100; box.infos = function(str){ return this.name+"---"+this.age+"---"+str; //this 当前对象 } alert(box.name); var con = box.infos("吃饭那"); alert(con);
构造函数
function person(name,sex,age){ this.name = name; //this.name属性 name参数 习惯上 属性名称==参数 this.sex = sex; this.age = age; this.show = function(){ alert(this.name+"---"+this.sex+"---"+this.age); } } var obj1 = new person("zhangsan","nan",18); //alert(obj1.sex); obj1.show(); var obj2 = new person("lisi","nv",20); obj2.show(); //注意: this 代表当前对象,obj1和obj2两者之间是独立的,函数内部只能用this访问属性和方法
构造和 工厂模式 不同:
1 构造方式不会显示创建对象 将属性赋值给 this ,不需要return 对象
2 工厂 在方法内部创建 object对象 返回object对象 ,属性和方法都是赋给object对象
function createobject(name,age){ var obj = new object(); obj.name = name;// obj.name 属性 name参数 obj.age = age; obj.run = function(){ //在obj对象中 调用obj对象的属性 this 代表的当前对象*** return this.name +"----" + this.age +"运行中...."; } obj.say = function(){ return "今天天气不错"; } return obj; } var box1 = createobject("张三",18); alert(box1.name); //调用属性成功 alert(box1.run()); //调用方法成功 var box2 = createobject("李四",20); alert(box2.name); alert(box2.run());
原型模式1
function test(){ } //alert(test.prototype instanceof object); //自带该对象 prototype是object子对象 test.prototype.color = "red"; test.prototype.heights = "1.7"; test.prototype.widths = "1.2"; test.prototype.showinfo = function(){ alert(this.color+"---"+this.heights+"---"+this.widths); } test.prototype.getinfo = function(){ alert("aaaaa"); } var car1 = new test(); car1.getinfo();
原型模式2
function test(){ } //json数据定义属性和方法 test.prototype={ color:"red", heights:"1.7", widths:"1.2", showinfo:function(){ alert(this.color+"---"+this.heights+"---"+this.widths); }, getinfo:function(str){ alert(str); } } var car1 = new test(); car1.getinfo("abc");
混合模式:构造+原型
function blog(name,url,friend){ this.name = name; this.url = url; this.friend = friend; } blog.prototype={ test:"awt", showinfo:function(){ alert(this.name+"---"+this.url); }, gets:function(){ alert(this.friend); } } var peo = new blog("张三","http://www.baidu.com","李四"); peo.showinfo();
对象的遍历
for in 取到的值是该对象-obj的所有属性名及方法名
function ren(){ this.name="zhangsan"; this.age = "18"; this.leng="180"; this.demo = function(){ alert(this.name); } } var r = new ren(); for(var i in r){ //i是属性或方法名称 alert(r[i]); //取得是属性的值 或者是方法的定义代码 }
输出:aaa aaabbb aaabbbfunction(){alert(“ccc”)}
for in 的遍历过程就相当于循环取值,能取到多少个值,就执行多少次函数体。对象遍历时,可以当做数组一样处理,通过[]取值
函数封装:
function a(){ var t = 3; function _xx(){ alert(11+"****") ;} this.xx = function(){ return _xx; } } a.prototype = { oth:function(){ alert("普通方法"); } } var a = new a(); var b = a.xx(); // a.xx() ---> function _xx() //b(); a.oth(); // 缺陷: 1 占用内存 2 不利于继承
原型继承
原型的值可以是一个对象,也可以是null。通过”object.prototype._proto_”获取object原型的原型的时候,将会得到”null”,也就是说”object {}”原型对象就是原型链的终点了;
继承的时候,允许多传参,多传入的参数会被截取掉,不起作用;
var person = function(){}; person.prototype.say = function(){ alert("天气挺好"); } person.prototype.gongzi = 500; var programmer = function(){}; programmer.prototype = new person();//programmer的原型继承自person programmer.prototype.wcd = function(){ alert("明天天气也不错"); } programmer.prototype.gongzi=1000; var p = new programmer(); p.say(); //可以调用person的方法 p.wcd(); //可以调用programmer的方法 alert(p.gongzi); //1000
原型继承:用到原型链的概念
function person(name,age){//父 this.name= name; this.age = age; } person.prototype.sayhello = function(){ alert("属性name值"+this.name); } function student(){} ;//子 student.prototype = new person("李四",18);// 原型继承 student.prototype.grade = 3; student.prototype.test = function(){ alert(this.grade); } var s = new student(); s.sayhello();//李四 alert(s.grade);//3
js 继承:
call apply
call --》 obj.call(方法,var1,var2,var3....)
apply--> obj.apply(方法,[var1,var2,var3]);
function person(name,age,len){ this.name = name; this.age = age; this.len = len; this.say = function(){ alert(this.name+":"+this.age+":"+this.len); } } //call继承 function student(name,age){ person.call(this,name,age); } //apply继承 function teacher(name,age,len){ person.apply(this,[name,age,len]) } var per = new person("张三",25,"170"); per.say(); var stu = new student("李四",18); stu.say(); // 李四 18 undefined var tea = new teacher("王武",20,"180"); tea.say();
关键词:
instanceof 变量是否是对象的实例
delete 删除对象的属性
function fun(){ this.name = "zhangsan"; this.say = function(){ alert(this.name); } } var obj = new fun(); alert(obj.name); delete obj.name; //删除name属性 alert(obj.name);//undefined var demo = "lisi"; alert(demo); delete demo; //删除不了变量 alert(demo); //注意:delete 不能删除原型链中的属性和变量
call apply
function animal(){ this.name = "ani"; this.showname = function(){ alert(this.name); } } function cat(){ this.name = "cat"; } var an = new animal(); var c = new cat(); an.showname.call(c,","); // 通过call方法,将showname--》cat使用了 an.showname.apply(c,[]);
callee:返回正在执行的function对象,function 内容
arguments.callee 默认值 正在执行的function对象
var sum = function(n){ if(n<=1){ return 1; }else{ return n+arguments.callee(n-1); //在函数内部调用本函数 } } alert(sum(5));
arguments.length,参数个数
arguments.callee 引用函数自身
function test(a,b,c){ alert(arguments.length); alert(arguments[1]); //arguments如果是表示参数,可以遍历的 alert(arguments.callee); } test(1,2,3);
this 可以在函数内部定义属性/变量
this全局变量 global
var x = 1; function test(){ this.x = 0 //改变了 全局变量 x 值 } test(); alert(x);
构造函数内 this指当前对象
function test(){ this.name = "zhangsan"; //this表示当前对象 --》 t this.age = 18; } var t = new test(); alert(t.name);
在call apply中,this指第一个参数
var x = 0; function test(){ alert(this.x) } var o = {}; o.x = 1; o.m = test o.m.apply(); // 第一个参数指向全局变量x:0 o.m.apply(o); //第一个参数指向对象o中的变量:1;
运用apply实现两个数组的拼接
var a=[1,2,3]; var b=[4,5,6]; a.push.apply(a,b); console.log(a);
对象冒充
function person(name,age){ this.name = name; this.age = age; this.sayhi = function(){ alert("hi"); } } person.prototype.walk = function(){ alert("walk......"); } function student(name,age,grade){ this.newmethod = person; //冒充person对象,传递特权属性和特权方法给子类 this.newmethod(name,age) this.grade = grade; } var s1 = new student("zhangsan",15,5); //s1 是student 对象 ,继承person,拥有person所有属性和方法 s1.sayhi(); //注意 s1继承了 person中的特权方法和属性,没有继承共有方法和属性
上一篇: golang 堆排序
下一篇: 夜宵吃什么可以增肥,这些食物要注意了!