zoukankan      html  css  js  c++  java
  • 面向对象编程

    这是一篇简单介绍js面向对象的编程笔记

    一,js解析和执行

      js解析时,会先把var和function声明的变量和函数放到一个词法对象里,变量的值是undefined,函数则是一个引用,这是js变量提升的根本机制。

      如果一个变量没有声明就开始使用了,不论它是在局部还是全局使用,它都是挂在了window下,是个全局变量,这点和this指向很类似,this找不到直接调用者,也是直接指向window。

      如果变量名和函数名命名冲突了,则该命名最后指向的是函数。如果两个函数名重复了,则后面一个函数覆盖前面的,因为在js中,函数才是第一等公民。

        e.g. 
        console.log(a)//undefined
        var a = 1
        console.log(a)//1
    
        e.g.
        console.log(aa)//function aa() {console.log('bbbbb')}
        var aa = 1
        function aa() {
           console.log('aaaaa')
        }
        function aa() {
           console.log('bbbbb')
        }

    二,作用域

      js只有全局作用域和局部(函数)作用域,并且内部可以由内到外,从近到远,访问即止地层层访问外部变量,形成一条作用域链,而外部不能直接访问内部变量。

        e.g.
        var a = 1
        var b = function() {
            var c = 2+a
            console.log(c)
        }
        b()//3
        console.log(c)//undefined

    三,闭包

      一种访问局部变量的手段,通常指的是一个可以访问局部变量的函数。

      闭包一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,因此要注意控制性能,提高网页性能。

        e.g.
      var name = "The Window";
      var object = {
        name : "My Object",
            // 这个方法是返回了一个函数
        getNameFunc : function(){
          return function(){
            return this.name;
          };
        }
      };
        // 执行了object.getNameFunc()返回的函数,此时this找不到直接调用者,直接指向window
      alert(object.getNameFunc()());
    
        e.g.
      var name = "The Window";
      var object = {
        name : "My Object",
            // 这个方法是返回了一个函数
        getNameFunc : function(){
                // that指向的是object
          var that = this;
          return function(){
            return that.name;
          };
        }
      };
        // 执行了object.getNameFunc()返回的函数,此时this固定化成了object,弹出object.name
      alert(object.getNameFunc()());

    四,类与对象

      搞清楚js中的类,就需要明白三个概念:构造函数、原型对象,实例化和实例。

        e.g.
        function Person(name,age) {
            this.name = name;
            this.age = age
        }
        Person.prototype.hello = function () {
            console.log('Hello,I am '+this.name+',and I am '+this.age)
        }
        var xm = new Person('xiaoming',12)
        xm.hello()//Hello,I am xiaoming,and I am 12
        Person.prototype = {
            asset:12345
        }
        var xmm = new Person('xiaomingming',34)
        console.log(xm.asset)//undefined
        console.log(xmm.asset)//12345

    其中Person函数就是构造函数,Person.prototype指向的对象就是原型对象,xm就是实例

      那么在关键词new的过程中,大概发生了什么呢?

      1,一个新对象被创建了,继承Person.prototype原型对象里的属性。
      2,使用指定的参数调用构造函数Person,并将this指向新创建的对象。

      如果我们用自定义函数模拟过程,则:

        e.g.
        function Person(name,age) {
            this.name = name;
            this.age = age
        }
        function New(f) {
            return function() {
                var o = {
                    '__proto__':f.prototype
                }
                f.apply(o,arguments)
                return o
            }
        }
        var xmmm = New(Person)('xmmm',232)

      在js中,并没有真正的类的概念,只是用构造函数和原型对象模拟了类,其中原型对象是类的唯一标识,当且仅当两个对象继承自同一个原型对象的时候,我们才说它们是同一个类的实例。而初始化对象的构造函数则不能作为类的标识,通常构造函数的名字被用来当做类名了而已。

      instanceof 运算符
      实例 instanceof 类名 被用来判断一个实例是否继承自某个原型对象,返回布尔值。

      在上述例子中,原型对象也是对象,也具有原型对象,即原型对象的原型对象,以此类推。访问一个实例本身没有的属性或方法时,js会从原型对象上去找,原型对象上没有时,会从原型对象上的原型对象上去找,......这种像链式一样地继承机制就是原型链,和作用域链很类似。

      原型对象中constructor属性则是指向该原型对象的构造函数,在修改原型对象时,比如增删其属性时,可采用.符号操作,如Person.prototype.hello = s =>{console.log(s)},在实例person初始化的时候,该原型对象的constructor默认指向构造函数.

      但是如果直接给Person.prototype赋值对象型数据时,则需要显式指定constructor属性,否则原有的原型对象会被新对象所替代,而通过构造函数实例化的实例的__protoo__属性都会指向最新的Person.prototype对象。在这个改动之后实例化的实例均不能继承原有的原型对象的属性,改动之前的实例亦不能继承新原型对象的属性。

      实例,构造函数,原型对象,原型链之间的关系可以借助一张神图来说明关系

      this指针问题:

      1,总是指向方法的直接调用对象,在事件触发中指向触发该事件的dom节点对象

      2,指向new出来的实例

      apply和call均可以改变this指针,其区别仅仅是第二个参数的不同而已:

      f.call(o,a,b) === o.f(a,b) === f.apply(o,[a,b])

    五,封装

      一段代码能够实现某种功能,隐藏该代码的细节,仅对外开放接口去使用该功能代码,即是对该功能代码的封装。

    六,继承

      继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。具有的方式可能是复制,可能是引用。

      从对象层面上来看继承:

      1,复制

            var zsh = {
                name :'zsh',
                age:23
            }
            var job = {
                job:'programer',
                language:'fe'
            }
            for (var key in job){
                zsh[key] = job[key]
            }
            console.log(zsh)//{name: "zsh", age: 23, job: "programer", language: "fe"}    

    涉及到深浅复制参考:http://www.cnblogs.com/zhouxiaohouer/p/8037729.html

      2,Object.create(proto[, propertiesObject])

      es5里的方法,注意兼容性。

      参数
      proto 新创建对象的原型对象。
      propertiesObject 可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。
      返回值
      在指定原型对象上添加新属性后的对象。

      从类的层面上来看继承:

            // 创建父类
            // 创建子类
            // 建立联系,修正构造函数
            // 实例化
            function Father() {}
            function Son() {}
            Son.prototype = Object.create(Father.prototype)
            // 此时,Son.prototype.constructor指向的是function Father() {},我们最好是将其修正过来
            Son.prototype.constructor = Son

    七,多态

      '见人说人话,见鬼说鬼话。'

      根据不同的参数个数,调用不同的方法,实现不同的功能

      本质上是检测arguments中数据类型来做对应的操作,将差异化的处理方式通用封装处理。

        e.g.
        function duotai(a,b,c,d,e,f) {
            console.log(duotai.length)//返回形参个数
            console.log(arguments.length)//返回实参个数
        }
        duotai(1,2,3,4)//6 4
    
        e.g.
        function add() {
            var result = 0
            for (var i = 0 ;i<arguments.length-1;i++){
                result += arguments[i]
            }
            return result
        }
        add(1,2,3,4,6,7,8)//31
        add(343,567,8456,234)//9600
  • 相关阅读:
    硬盘SSD、HDD和SSHD都是什么意思?哪种类型硬盘最好?
    记录vlookup的小问题
    找到两个字符串中相同的部分| 对字符串list后的奇妙发现
    jiayan:Cannot read model 'jiayan.klm' (utilfile.cc:74 in util::OpenReadOrThrow threw ErrnoException because `-1 == (ret = _open(name,
    windows下装kenlm
    每日一题力扣98 验证二叉搜索树
    每日一题力扣230 二叉搜索树中的第K小的元素
    每日一题力扣538 把二叉搜索树转换为累加树
    每日一题力扣530 二叉搜索树的最小绝对查
    每日一题力扣700 二叉搜索树中的搜索
  • 原文地址:https://www.cnblogs.com/zhouxiaohouer/p/8067709.html
Copyright © 2011-2022 走看看