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> varli=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中的特權方法和屬性,沒有繼承共有方法和屬性