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
  • 相关阅读:
    973. K Closest Points to Origin
    919. Complete Binary Tree Inserter
    993. Cousins in Binary Tree
    20. Valid Parentheses
    141. Linked List Cycle
    912. Sort an Array
    各种排序方法总结
    509. Fibonacci Number
    374. Guess Number Higher or Lower
    238. Product of Array Except Self java solutions
  • 原文地址:https://www.cnblogs.com/zhouxiaohouer/p/8067709.html
Copyright © 2011-2022 走看看