1. 程式人生 > 實用技巧 >JS面向物件

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