面向对象

面向对象,原型链的基本理解。

section 1

  1. 构造函数中的this指的就是通过构造函数实例化出来的具体的某个实例对象。
  2. 如果构造函数显示的返回基本的数据类型,那么和不返回效果一致,都返回原来的this,就是具体的某个实例对象.
  3. 如果构造函数显示的返回一个对象,那么实例化出来的实例对象就是你显示返回的对象.
  4. 函数的本质也是引用的类型,函数的名字实质上是内存的地址。
  5. 原型方法里的this指的是具体的通过某个构造函数创建的实例。
  6. 面向对象编程
//面向对象编程
/*创建对象*/
function ChangeStyle(div,btn) {
    this.div = document.querySelector(div);
    this.btn = document.querySelector(btn);
}
/*在prototype下的方法是所有的实例都可以共用的*/
ChangeStyle.prototype.init = function () {
    var _this = this;
    this.btn.onclick = function () {
        _this.div.style.width = "300px";
        _this.div.style.height = "300px";
        _this.div.style.backgroundColor = "cyan";
    }
}
/*创建实例*/
var cs = new ChangeStyle(".box1","button");
/*共享对象的方法*/
cs.init();



section2

  1. 可以通过三种方式自定义函数:函数声明函数表达式new Function、还有一种系统提供的函数,比如Object、String、Number(主要用前两种自定义函数)。
  2. 通过函数声明建立的函数可以先调用再申明。
  3. 函数有三种调用方式:

    • 普通函数(调用者(this)是window,但是在es5的严格模式中this是undefined)。

      
      function foo(){
           'use strict'
           console.log(this);
       }
      foo();//ES3中,this就是window;ES5的严格模式下,this为undefined
      
    • 对象方法,{}构造出来的函数也是Object的一个实例,和new Object出来的函数是等效的。

         var obj = {};
           obj.info = 'hello';
           obj.showInfo = function(){
           console.log(this.info);
           }
         foo.showInfo();//对象方法中的this就是调用方法的对象
      
    • 构造函数的调用.

          function Foo(info) {
              this.info = info;
              this.showInfo = function() {
                  console.log(this.info);
              }
          }
          Foo.prototype.fn = function() {
              //原型对象中的this就是实例对象
              console.log(this.info);
          }
          var foo = new Foo("hello");
          foo.showInfo();//对象方法中的this就是实例对象
      
    • call apply. call和apply这两个方法都可以用来调用函数

      • 作用:可以改变函数中this的指向,借用别的对象的方法。
      • 差异:两者的第一个参数都是传谁this就指向谁,null表示不改变this指向,后面的函数自带的参数apply要以数组的方式传入。
    • 调用严格模式:加上“use strict”。

      function foo(a,b){
      console.log(a + b);
      }
      foo.call(null,1,2); foo.apply(null,[1,2]); //改变this指向
      var obj1 = {
                info : 'Tom'
       };
       var obj2 = {
               info : 'Jerry'
       }
       window.info = 'Spike';
      var showInfo = function(){
               console.log(this.info);
      };
      showInfo();
      showInfo.call(obj1);
      showInfo.call(obj2); //调用call或apply都会自动执行对应的函数,而bind不会执行对应的函    数,只是返回了对函数的引用
      
  4. bind:也是改变this的指向,参数传谁this就指向谁(IE678不兼容)。
    • 和call、apply的区别:call、apply需要调用一次函数才能改变this的指向,而bind则不用。
  5. 属性写在对象里,方法写在原型里。
  6. new到底做了什么事情?
    • 在内存开辟一块存储空间,这块内存地址给了this
    • 把构造函数的属性以及传递的参数放到了这块内存空间
    • 把this的值返回给实例变量
  7. 构造函数中的this和原型中的this指向相同,都是指向实例对象。

prototype、constructor、proto之间的联系与区别

  1. 构造函数中都有一个原型属性prototype,该属性是引用类型.
  2. 原型对象中有一个属性constructor,该属性指向构造函数。
  3. 实例当中都有一个属性proto,该属性指向构造函数的原型prototype,改属性不是标准属性,不可以在编程中显示使用,该属性是浏览器自己使用的。
  4. prototype和proto之间的区别:
    • 这两者都是指向同一个对象。
    • prototype站在构造函数的角度来说的
    • proto站在实例的角度来说的
    • 函数也是对象,但是对象不一定是函数

this

A this value is a special object which is related with the execution context. Therefore, it may be named as a context object (i.e. an object in which context the execution context is activated). this是和执行上下文环境息息相关的一个特殊对象。因此,它也可以称为上下文对象(激活执行上下文的上下文)。 a this value is a property of the execution context, but not a property of the variable object. this是执行上下文环境的一个属性,而不是某个变量对象的属性。这个特点很重要,因为和变量不同,this是没有 一个类似搜寻变量的过程。当你在代码中使用了this,这个 this的值就直接从执行的上下文中获取了,而不会从作用 域链中搜寻。this的值只取决中进入上下文时的情况。


section3

  1. 高阶函数

    • 作为参数的函数

      • 引用类型传递的是地址,所以在函数内部对引用类型值的修改会同步

          function foo(data){
                    // console.log(data);
                 data.push(5);
                 return data;
         }
         var arr = [1,2,3,4];
         var ret = foo(arr);
         console.log(arr,ret); //都是返回[1,2,3,4,5]
        
      • 基本类型传参传递的是实际的值,所以在函数内部对参数的修改不影响传递进来的参数

             function foo(data){
                 data = 456;
                 return data;
             }
             var d = 123;
             var d1 = foo(d);
             console.log(d,d1);
        
    • 作为返回值的函数
    • 函数作为参数传参,即是回调函数

      ```javascript
      

      // 回调函数
      var callback = function(data){

         console.log("通知:"+data);
      

      }

      //相当于文员
      function ajax(data){

         //1、创建XHR对象
         var xhr = new XMLHttpRequest();
         //2、发送前的准备工作
         xhr.open('get','http://localhost/abc.php',true);
         //3、执行发送动作
         xhr.send(null);
         //4、指定回调函数
         xhr.onreadystatechange = function(){
             //4表示服务器端已经完全返回结果,但是数据是否正确还不确定
             if(xhr.readyState === 4){
                 //200表示服务器返回的数据是正确的
                 //404表示没有找到请求的资源
                 //500服务器端错误
                 if(xhr.status === 200){
                     // var result = '空调坏了';
                     // var result = '服务器挂了';
                     var result = xhr.responseText;
                     data(result);
                 }
             }
         }
      

      }
      ajax(callback);

  1. 数组的排序

    • 给数组排序

         var arr = [1,2,3,4,5,6];
         arr.sort(function (a,b)) {
             //如果返回值大于0,则从大到小排序
             //如果返回值小于0,则从小到大排序
             return a - b;
         }
         console.log(arr);
      
    • 给对象排序

         var arr = [1,2,3,4,5,6];
         arr.sort(function (a,b)) {
             //如果返回值大于0,则从大到小排序
             //如果返回值小于0,则从小到大排序
             return a - b;
         }
         console.log(arr);
      
  2. 函数的理解
  3. 简单理解,对象就是键值对的集合

section4


网站的基本知识

  1. 常见的通信协议
    • http/https:超文本传输协议
    • ftp:传输协议
    • mstp/pop3: 邮件传输协议
  2. 多个ip地址可以对应一个域名,域名与ip地址是通过DNS域名解析互相连接的
  3. 端口:用来唯一确定计算机上的应用程序,一个端口就是对应一个应用程序,端口的数值0-65535,一般使用1024-65535的端口
  4. 同样的域名同时请求地址数量是有限制的
  5. 静态网站:资源都是静态的(提前准备好的)缺点:可维护性低,无法进行交互
  6. 动态网站:绝大所数html页面是动态生成的,数据和标签页面是分开的。php/java/.net/nodejs
  7. MAMP的组成:
    • M:Mac系统
    • A:Apache 提供网页服务
    • M:mysql 数据库(其他数据库oracle,sqlserver,db2,access,nosql,mongodb,redis,memercache)
    • P:php 用来开发后台程序(做网站)
  8. 传统的网站访问方式是同步模式
  9. 同步和异步发生在客户端和服务器端之间
  10. ajax达成的效果:实现页面的局部刷新,不阻塞页面

###跨域(jsonp)

  1. 协议、端口、域名只要有一个不一样,就是跨域。
  2. ajax出于安全问题的考虑,设计之初就不支持跨域获取数据。
  3. 因此要通过别的办法解决跨域问题(flash、动态创建script标签(就是jsonp的本质、h5)
  4. jsonp: json with padding
  5. 后台返回数据中时间戳的作用:解决缓存问题
  6. jQuery中ajax方法的jsonp参数的作用:改变url参数的key
  7. data = JSON.parse(data);将字符串转换为json数据。

数据库简单操作(增删改查)

  1. 增:insert into 表名(字段信息) values (字段对应的数据)
  2. 删:delete * from 表名 where 条件
  3. 改:update 表名 set 字段名 = 字段值,字段名 = 字段值
  4. 查:select * from 表名 where 条件

section5

构造函数-原型-实例对象-原型链-constructor的关系

  1. 堆栈
  2. 实例对象和原型对象组成了一条链式结构,它们之间通过proto连接

    P –> person.prototype –> Object.prototype –> NULL

  3. 对象的本质:无序的键值对集合。

  4. 所有原型链的末端都是Object,即所有的对象都直接或间接的继承自Object。
  5. 原型链是javascript中继承的本质。
  6. constructon一般用来区分该对象是谁的构造函数的。
  7. 所有的方法都是FUnction的实例。
  8. 实例对象.__proto__ == 构造函数.prototype。
  9. javascript中的函数是由浏览器根据FFunction实例化来的,
  10. Math不是方法,不能new 一个实例对象,Math是一个对象。
  11. 函数一定是对象,对象不一定是函数。
  12. 三张图:

    • 构造函数-原型-实例对象-constructor-1

      构造函数-原型-实例对象-constructor-2
    • 原型链
      原型与原型链-1

      原型与原型链-2

    • 函数与Function的关系

    • 关于constructor

  13. 函数的三种角色

    • 普通函数
    • 构造函数
    • 对象
  14. 所有的函数都有prototype(有构造函数有关)和__proto__(普通函数)属性。
  15. instanceof:判断是否是指定对象的实例。
  16. 如果构造函数的原型在原型链上,那么原型链开始的那个实例就是所有原型所属的构造函数的实例。
  17. 属性判断:判断某个属性是否属于某个对象:
    • in:既可以判断对象上的属性,也可以判断原型对象上的属性
    • hasOwnproperty:判断对象中是否有某个属性
      • 语法:对象名:hasOwnproperty(‘属性名’)

类型判断:

  1. 数据类型:

    • 基本类型:number/string/boolean/null/undefined
    • 引用类型:Object(Function/Array/Date/String/RegExp/Boolean/Error等
    • typeof:类型判断,只能判断出string、number、object、undefined、function、boolean
  2. 判断Object类型和Array类型

内容总结

  1. 所有的构造函数都有一个原型属性prototype属性,该属性是一个对象。
  2. 原型对象都有一个conctructor属性,该属性指向原型所属的构造函数。
  3. 所有的实例都有一个__proto__属性,该属性指向产生该实例的构造函数的原型对象,该属性不是标准的属性,是给浏览器自己使用的。
  4. 所有的原型对象都有一个__proto__属性,该属性指向另一个构造函数的原型,构成原型链。
  5. 所有的函数都有一个属性__proto__,该属性指向Function的原型prototype(所有的函数都是Function的实例)。
  6. Function函数是本身的实例(Function.__proto__ === Function.prototype)。
  7. 对象的本质是无序的键值对的集合。

__proto__与prototype的关系

  1. prototype是从构造函数的角度来说的
  2. __proto__是从实例对象来说的
  3. 这两个属性指向同一个对象,都指向原型对象。

函数中的三种角色

  1. 普通函数
  2. 对象
  3. 构造函数
  4. 函数是什么角色取决于它的调用方式

    function foo(){};
    
    foo(); //作为普通函数,此时比较关心__proto__属性
    
    var f = new foo(); //作为构造函数,此时比较关心prototype属性
    
    foo.info = "hello"  //此时就是对象
    foo.showInfo = function() {
            console.log(this.info);
    }
    

section6

###jsonp跨域

原生jsonp

  1. 跨域:只有域名,端口,协议都一样才叫同源,否则有其中一个不同就是跨域。
  2. ajax不予许跨域获取数据所以需要想办法解决跨域获取数据的问题。
  3. 解决方案:flash、applet、name、h5等,现在主流的解决方案是jsonp。
  4. jsonp的本质:动态创建script标签,通过script标签的src属性发送请求,请求返回的内容是一段JavaScript代码(函数调用,一个变量)

    //本质是动态创建script标签,通过script标签的src属性发送请求
    var script = document.createElement('script');
    script.src = '要请求文件的路径';
    var head = document.getElementTagName('head')[0];
    head.appenChild(script);
    
  5. 动态创建的script加载数据的方式是异步的。

jQuery中的jsonp

  1. jsonp和jsonpCallback分别是用来重命名

    此处有代码 // jsonp-test
    

url的标准格式

  1. scheme://host:port/path?query#fragment
  2. scheme: 协议:http/https/ftp/smtp
  3. host: 域名/IP
  4. port: 端口
  5. path: 路径
  6. query:从?开始,多个参数之间用?隔开,单个参数用=隔开 ?key1=value1$key2=value2
  7. fragment: 锚点:

继承

  1. 原型链:实例对象和原型对象之间通过__proto__联系起来的的链式结构。
  2. 继承:把别人的拿过来(属性和方法),自己的还是自己的

继承的方式

  1. 原型继承:

    • 原型继承的缺点:
      • 没有办法在不影响所有实例的情况下给要继承的构造函数传参。
      • 继承的构造函数中的引用类型对于所有的实例来说是共享的。
    function Animal(name) {
         this.name = name;
         this.lover = ['meat','cake','cheese','juice'];
     }
     Animal.prototype.showName = function () {
         console.log(this.name);
     }
     function Tom(color) {
         this.color = color;
     }
     /*将Tom的原型对象指向Animal的实例对象*/
     Tom.prototype = new Animal('Tom');
     Tom.prototype.catchMouse = function () {
         console.log(this.name +"抓到Jerry了!!");
     }
     var tom = new Tom("grey");
     tom.catchMouse();
     tom.lover.push('peal');
     console.log(tom.lover);
    
     var jerry = new Tom('green');
     console.log(jerry.color);
     jerry.catchMouse();
     /*继承的构造函数的引用类型对于所有的实例来说是共享的*/
     console.log(jerry.lover);
    
  2. 借用构造函数继承

    • 缺点:只能继承构造函数中的成员,不能继承构造函数中的方法
    function Animal(name){
             this.name = name;
             // this.showName = function(){
             //     console.log(this.name);
             // }
         }
         // Animal.prototype.showName = function(){
         //     console.log(this.name);
         // }
         function Mouse(nickname,name){
             //这样调用的话Animal中的this是谁?Mouse的实例对象
             Animal.call(this,name);
             // thia.name = '老鼠';
             this.nickname = nickname;
         }
    
         var m = new Mouse('杰瑞','老鼠');
         // console.dir(m);
         // m.showName();
         console.log(m.name);
         console.log(m.nickname);
    
         var m1 = new Mouse('贝塔舒克','mouse');
         console.log(m1.name);
         console.log(m1.nickname);
    
  3. 组合继承(原型继承和借用构造函数继承)

  • 目的:属性都使用实例的,方法都使用构造函数的。

    function Person(name,sex) {
          this.name = name;
          this.sex = sex
          this.score = [100, 200, 150, 180, 200];
      }
      Person.prototype.showName = function () {
          console.log(this.name);
      }
      Person.prototype.showScore = function () {
          console.log(this.score);
      }
      function Student(name,age,sex) {
          /*将构造函数Person的this指向构造函数Student的实例对象
          * 这样Student的实例对象就可以使用Person的属性
          * */
          Person.call(this,name,sex);
          this.age = age;
      }
      /*将构造函数Student的原型对象指向构造函数Person的实例对象
      * 这样Student的实例对象就可以使用Person的原型对象的方法.
      * */
      Student.prototype = new Person();
    
      Student.prototype.showAge = function () {
          console.log(this.name+"的年龄为"+this.age);
      }
      var stu = new Student("张三","12","男");
      console.log(stu.name);
      console.log(stu.age);
      console.log(stu.sex);
      console.log(stu.score);
      stu.showAge();
      stu.showScore();
    

命名空间

var nihao

面向对象三大特性

封装

继承(代码的重用)

多态: 对于同一种行为的不同表现状态

object.create();

section7

面向对象知识点

  • 对象
  • 构造函数
  • 实例对象
  • 原型对象
  • 原型链
  • 封装继承多态
  • 继承方式:原型继承、构造函数继承、组合继承
  • 函数的三种角色:
  • this

面向过程、面向对象的编程思维

  • 面向过程:命名冲突,不方便代码重用。
  • 面向对象:从一定程度上避免命名冲突,方便代码重用。
  • 面向对象的程序风格:构造函数(属性)+ 原型(方法)、实例化之后可以执行原型上的方法,实例化的时候构造函数也会执行。
  • 原型的另一种写法

    • 以对象的方式来写
    • 要在最前面加上constructor:构造函数名字
    • 一般会体提供一个入口函数init
    • 一系列的方法,这些方法是可以相互调用的
    • 这些方法也可以不相互调用,通过实例对象直接调用(相互独立的功能)
    function Foo(){};
    Foo.prototype = {
           constructor: Foo,
           init: function(){},
           autoplay: function(){},
           ......
    }
    
  • 避免命名冲突的终极解决方案:模块化。

  • SVN Git(代码托管)。

案例

  • 改变div样式
  • 选项卡
  • 轮播图
  • 表格排序

作用域

全局作用域

  • 所有在全局作用域中的变量和成员都是window的成员
  • delete:删除对象的属性,而不是方法
  • 通过var声明的变量是不可以被delete方法删除的,如果不适用var声明的变量是可以被delete删除的
  • 全局作用域中的成员对所有的函数都是可见的
  • delete删除数组元素的时候,数组的长度是不变的,即会删掉那个元素,但该元素仍然有一个占位符在。

    var a = 1;
    b = 2;
    this.c = 123;
    var arr = [1, 2, 3, 4, 5];
    
    delete: a;
    delete: b;
    delete: this.c;
    delete: arr[2];
    
    console.log("a" in window); //true
    console.log("b" in window); //false
    console.log("c" in window); //true
    console.log(arr);
    
  • in:判断某个属性是否在某个作用域中

    console.log("abc" in window); //true or false
    

函数作用域

  • 函数作用域中的变量只能在函数内部使用,对外不可见。

块级作用域

  • 花括弧{}形成块级作用域,但是在JavaScript中没有块级作用域的概念.

预解析

1.预解析

  • 预解析的时候如果遇到同名的变量或者函数,以函数为准,即函数的优先级高于变量.
  • 预解析的时候的优先级:函数》形参》声明。
  • 全局作用域:所有的全局变量和函数声明都提前了。
  • Javascript中的数据类型是可变的。
  • 函数作用域:所有的局部变量和内部的函数声明以及形参都提前了。
  • 变量提前仅仅是变量名提前,但是赋值没有提前。

    var a = 456 //等价于
    var a;
    a = 456;
    

2.执行

  • 从上到下逐行执行

作用域链:作用域之间形成的链(嵌套函数)

  • 访问变量的规则是从里到外,不可以反过来

    var a = 10;
    function foo() {
       var b = 20;
       function fn() {
           var c = 30;
           console.log(a + b + c); //60
       }
       fn();
    }
    foo();
    

闭包

  • 闭包:函数的嵌套形成闭包,里面嵌套的函数一定要有返回值,封闭的包裹。
  • 闭包的组成:
    • 函数代码块(内层函数)
    • 函数的父级作用域
  • 闭包的作用:
    • 函数外部可以访问函数内部的变量(延长函数变量的生命周期)
    • 缓存中间状态值
  • (词法作用域)静态作用域:访问变量的时候取决于函数的定义位置,而不是调用位置
  • 闭包可以做什么

    • 闭包可以形成一个封闭的环境,然后对外开放一个接口
    • 闭包用来访问函数内部的数据

      function foo(rate) {
                var money = 100000;
                return function () {
                    return  money * rate;
                }
            }
            var fn = foo(0.001);
            var ret = fn();
            console.log(ret);
      

自执行函数


打印函数时各参数的意思

  • length:形参的个数
  • arguments:实参的个数,它不是数组,叫类数组或者关联数组

    • arguments[i]可以用来替代第几个形参
  • caller: 函数的调用者.

section8

闭包补充

  • 垃圾回收机制如果一个数据不存在任何引用,那么这个数据就成了垃圾
  • C/C++的垃圾回收机制是手动的,(程序员自己分配内存,释放内存)

    var obj = {name: 123}
    obj = null;
    console.log(obj.name) // undefined
    //name就成了垃圾,等待被回收
    
  • 闭包的应用场景:获取函数内部的变量,并且可以修改(通过修改返回来的那个函数).

浏览器

  • 浏览器:应用软件(多线程渲染页面,Javascript的解析运行,网络通信)。
  • 多线程:一个线程就是处理一个任务。
  • 浏览器运行时是多线程的。
  • Javascript程序的运行是单线程的。

事件队列

  • 如下的三种情况,任务会放到事件队列,但是先不执行
    • 定时函数(延时到期)。
    • 事件函数(触发事件)。
    • ajax的回调函数(服务器端返回正常的数据)。
  • 这三种任务的执行条件是(先满足第一个条件,再看是否满足第二个条件)
    • 主线程已经空闲(Javascript代码执行完毕)。
    • 需要特定的条件来触发。
  • 定时器的延时是有浏览器的兼容性的(有的4ms,有的6ms,8ms)

事件对象

  • p标签、h标签不可以嵌套块级元素

默认行为

  • 系统给标签默认自带的行为:a标签跳转,拖动文字和图片变半透明等行为。
  • 阻止默认行为:

    a.onclick = function() {
           只能阻止默认行为,不能阻止冒泡,但是jQuery中可以同时阻止两者
           return false;
    }
    //另一种写法
    a.onclick = function() {
       if(e) {
           e.preventDefault();
       } else {
    
       }
    }
    
  • 阻止