2017-03-21 JS面向对象笔记

基本的面向对象

  • 拥有自己的属性
  • 拥有自己的方法
  • 数值,字符,布尔,对象, undefined
  • 数组, array

基本面向对象的写法

var dog = {
        name:'小花',
        age:1,
        friendDogs:['小黄','小虎'],
        eat:function(someThing){
        console.log('吃' + someThing);
        },
        run:function(someWhere){
        console.log('跑' + someWhere);
        }
}
dog.eat('奶');
dog.run('树下');

面向对象的常用写法

function dog(){
        var obj = new Object();
        obj.name = '未定义';
        obj.age = 0;    
        obj.eat = function(someThing){
         console.log(this.name + '吃' + someThing)
        };
        obj.run = function(someWhere){
        console.log(this.name + '跑' + someWhere);
        }
        run obj;
}
var smallDog = dog();
smallDog.name = '小花';
smallDog.age  = 1;
smallDog.eat('奶');
var bigDog = dog();
bigDog.name = '大花';
bigDog.age = 1;
bigDog.run('棠下');
bigDog.eat('肉');

this 对象的认识

  • this : this 所在的函数(方法)属于哪个对象,那么 this 就表示哪个对象
  • this 在事件指令中表示事件源
  • window.所有的全局变量都是它的属性,所有的全局的函数都是它的方法
  • this 在定时器表示 window
  • 任何一个函数都可以通过 New+ 函数调用创建一个对应的对象
  • 如果遇到 new 函数调用会创建一个新的对象,那么这个函数就属于新创建的对象,所以 this 表示这个对象

通过构造函数创建对象

  • 构造函数
    形式:第一个字母都是大写
    new: 可以创建一个对象返回来
创建对象,使用构造函数
function Dog(name,age,dogFriends){
        this.name = name;
        this.age = age;
        this.dogFriends = dogFriends;
        this.eat = function(someThing){
                  console.log(this.name + '吃' + someThing);
        }
        this.run = function(someWhere){
                  console.log(this.name +  '跑' + someWhere);
        }
}
//通过构造函数创建对象
var smallDog = new Dog('小花',1,['小虎','小明']);
smallDog.eat('奶');
smallDog.run('教室');

var bigDog = new Dog('大花',1,['大虎','大明']);
bigDog.eat('肉');
bigDog.run('树下');

通过构造函数创建对象优化


    //创建对象,使用构造函数
    //优化:就是使用json把参数保存起来,直接传递json
    function Dog(option) {
        var option = option ||{};

        this.name = option.name;
        this.age = option.age;
        this.dogFridends = option.dogFridends;
        this.eat = function (someThing) {

            console.log(this.name +'吃' + someThing);
        }
        this.run = function (someWhere) {
            console.log(this.name +'跑'+someWhere);
        }



    }

    //2.通过构造函数创建对象
    var smallDog = new Dog({name:'小花',age:1,dogFriends:['小虎','小明']});
    console.log(smallDog.name);
    console.log(smallDog.age);
    smallDog.eat('奶');
    smallDog.run('教室');

    var bigDog = new Dog({name:'大花',age:8,dogFriends:['大虎','大明']});
    console.log(bigDog.name);
    console.log(bigDog.age);
    bigDog.eat('肉');
    bigDog.run('棠下');

  • 当我们使用不同的对象调用函数的时候,这个函数不是同一个函数
  • 每次创建对象,调用函数的时候,这个函数都需要重新创建
  • 但是这两个函数功能是一样的,我们每必要每次创建一个对象都使用新的函数
  • 所以我们需要这个 eat 函数可以共用,无论哪个对象调用,都是同一个函数

原型属性的使用

  • 原型属性:可以扩展属性和方法,就是一个构造函数的共享库,以后所有创建的新的对象,都可以使用这个共享库中的方法以及属性
  • 优点是降低了创建方法的成本
Array.prototype.eat = function(){
        console.log('数组会吃东西');
};
Array.prototype.run = function(){
        console.log('数组会跑');
};

//原型库的第二种写法
Dog.prototype = {
        eat:function(someThing){
                  console.log(this.name + 
'吃' +someThing);
        },
        run:function(someWhere){
                  console.log(this.name + '跑' +someWhere);
        }
};

通过构造函数创建对象最终版

  • 要把属性也放在原型库中,使用一个初始化方法 _init
  • 在构造函数中调用初始化方法,然后把这个初始化方法放在原型库中,初始化方法用来初始化属性
function Dog(option){
        this._init(option);
}
Dog.prototype = {
        _init:funtion(option){
                var option = option || {};
                this.name = option.name;
                this.age = option.age;
                this.dogFriends = option.dogFriends;
          },
          eat:funtion(someThing){
                  console.log(this.name + '吃' + someThing);
          }
}
ar smallDog = new Dog({name:'小花',age:1,dogFriends:['小虎','小明']});
    console.log(smallDog.name);
    console.log(smallDog.age);
    smallDog.eat('奶');
    smallDog.run('教室');

    var bigDog = new Dog({name:'大花',age:8,dogFriends:['大虎','大明']});
    console.log(bigDog.name);
    console.log(bigDog.age);
    bigDog.eat('肉');
    bigDog.run('棠下');

面向对象创建一个矩形

 /*1.创建一个构造函数用来创建矩形*/
    function Rect(option){
        this._init(option)
    }

    /*2.给rect设置原型对象*/
    Rect.prototype = {
        _init:function(option){
            var option = option ||{};
            /*2.1设置属性*/
            /*2.11设置添加的父标签的id*/
             this.parentId = option.parentId;
            /*2.12设置宽度和高度*/
            this.width = option.width||100;
            this.height = option.height ||100;
            /*2.13设置位置*/
            this.left = option.left ||100;
            this.top = option.top ||100;
            /*2.14 设置其他属性*/
            this.background = option.background ||'blue';
            this.borderRadius = option.borderRadius ||10;
            this.border = option.border ||0;





        },
        /*设置显示方法*/
        render:function(){
            /*1.创建一个父标签,用来添加我们的矩形*/
            var parentNode = document.getElementById(this.parentId);
            var childremNode = document.createElement('div');
            parentNode.appendChild(childremNode);
            /*2.设置子标签的样式*/
            childremNode.style.position = 'absolute';
            parentNode.style.position = 'relative';
            childremNode.style.width = this.width +'px';
            childremNode.style.height = this.height +'px';
            childremNode.style.left = this.left +'px';
            childremNode.style.top = this.top +'px';
            childremNode.style.background = this.background;
            childremNode.style.borderRadius = this.borderRadius +'px';
            childremNode.style.border = this.border;




        }

    }

    /*创建一个矩形*/
//    this.width = option.width||100;
//    this.height = option.height ||100;
//    /*2.13设置位置*/
//    this.left = option.left ||100;
//    this.top = option.top ||100;
//    /*2.14 设置其他属性*/
//    this.background = option.background ||'blue';
//    this.borderRadius = option.borderRadius ||10;
//    this.border = option.border ||0;

    var myRect = new Rect({parentId:'main',width:200,height:100,left:200,top:200,background:'red',borderRadius:10,border:'1px solid #ccc'});
    alert(myRect);


    /*渲染*/
    myRect.render();

闭包的认识

  • 如果访问一个局部变量,但是出了作用域就访问不到,我们想要访问这个变量需要使用闭包
  • 闭包是在函数内部使用函数或者定义函数
  • 闭包作用域链条:就是子对象可以访问对象所有的属性,反之不可以
    就是访问变量的时候,会沿着作用域链条向上访问,不能反过来
  • 闭包的优点是延长变量的使用周期,缺点是耗费性能
//第一步
function sum(){
        var num = 10;
        var result = function(){
                  console.log(num);
        }
        return result;
}
var result =  sum();
//这样可以把变量通过返回函数的形式传递出来
//实际上内部函数可以匿名
function sun(){
        var num = 10;
        return function(){
                  console.log(num);
        }
} 
var result = sum();
console.log(num);
//第二种写法
sum()()
//这就是匿名函数传递参数

匿名函数自调

  • 匿名函数自调内部可以继续使用匿名函数自调
  • 当访问变量的时候,会先从自己的作用域访问对应的变量,如果没有,就沿着作用域链条向上访问,知道找到为止,如果没有返回未定义
  • 为了提高性能一般不要多层嵌套匿名函数自调
  • 为了提高性能一般不要使用全局变量
var num = 20;
(function(){
        (function(){
               console.log(num);
        })()
})(num)
  • 当使用全局变脸的时候,会把 window 中的所有的东西遍历一遍,直到找到对应的变量
for(var key in window){
}

访问变量的简单认识以及应用

//第一种写法,两次定义全局变量极其消耗性能,两次遍历 window
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn1');
//第二种写法,匿名函数的自调,只遍历一次 window 且是函数内部的局部变量
(function(){
        var d = document;
        var btn1 = d.getElementById('btn1');
        var btn2 = d.getElementById('btn2');
})()
//第二种写法的变形,将document当作参数传递进去
(functiojn(document){
        var btn1 = document.getElementById('btn1');
        var btn2 = document.getElementById('btn2');
})(document)

高级排他

var lis = document.getElementById('li');
//用来记录上一个移动到的位置
var lastIndex = 0;
for(var i = 0 ; i < lis.length;i++){
        (function(index){
                lis[i].onmouseover = function(){
                  lis[lastIndex].className = "";
                  this.className = 'curr';
                  lastIndex = index;
                  }
        })(i)
}

使用闭包实现数据截流

function throtte(delay,fn){
        var timer = null;
        return function(){
                clearTimerout(timer);
                timer = setTimerout(fn,delay)
        }
}

window.onresize = throtte(300,function(){
        alert(0);
})

你可能感兴趣的:(2017-03-21 JS面向对象笔记)