1. OOP基础

1.1面向对象编程OOP

1、语言的分类:
     ① 面向机器:汇编语言
     ② 面向过程:C语言
     ③ 面向对象:C++ Java PHP 等
 
2、面向过程与面向对象
     ① 面向过程:专注于如何去解决一个问题的过程步骤。编程特点是由一个个的函数去实
                            现每一步的过程步骤,没有类和对象的概念。
     ② 面向对象:专注于由哪一个对象来解决这个问题。编程特点是出现了一个个的类,从
                           类中拿到对象,由这个对象去解决具体问题。
 
对于调用者来说,面向过程需要调用者自己去实现各种函数;而面向对象,只需要告诉调用者对象中具体方法的功能,而不需要调用者了解方法中的实现细节。
 
[面向对象的三大特征]
继承、封装、多态
JS可以模拟实现继承和封装,但是无法模拟实现多态,所以说JS是一门基于对象的语言,而并非是面向对象的语言!
 

1.2类和对象

1、类:一类具有相同特征(属性)和行为(方法)的集合。
  eg:人类-->属性:身高、体重、性别 方法:吃饭、睡觉、说话
 
2、对象:从类中,拿出具有确定属性值和方法的个体。
  eg:张三-->属性:身高180 体重160 方法:说话-->我叫张三
 
3、类和对象的关系:
  类是抽象的,对象是具体的(类是对象的抽象化,对象是类的具体化)
 
类是一个抽象的概念,只能说类有属性和方法,但是不能给属性赋具体的值。
eg:人类有姓名,但是不能说人类的姓名是什么
 
对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体
eg:张三是人类的一个个体,可以说张三的姓名是张三,也就是张三对人类的每一个属性进行了赋值,那么张三就是由人类产生的一个对象。
 
4、使用类和对象的步骤:
    ① 创建一个类(构造函数):类名必须使用大驼峰法则,即每个单词首字母都要大写。
        function Person(name,age){
this.name=name;
this.age=age;
this.say=function(content){
// 在类中,访问类自身的属性,必须使用this.属性 调用
alert("我叫"+this.name+",今年"+this.age+"岁。我说了一句话:"+content);
}
}
 ② 通过类,实例化(new)出一个对象。
var zhangsan = new Person("张三",18);

var obj = new 类名(属性1的具体值);

    obj.属性; 调用属性
    obj.方法; 调用方法
 
  ③ 注意事项:
      >>> 通过类名,new出一个对象的过程,叫做"类的实例化"
      >>> 类中的this,会在实例化的时候,指向新new出的对象;
    所以,this.属性 this.方法 实际上是将属性和方法绑定在即将new出的对象上面
    >>> 在类中,要调用自身属性,必须使用this.属性名。如果直接使用变量名,则无法访问对应属性。
      >>> 类名必须使用大驼峰法则,注意与普通函数区分。
 
5、两个重要属性:
    ① constructor:返回当前对象的构造函数。
        >>> lisi.constructor==Person; √
    ② instanceof:检测一个对象,是不是一个类的实例
        >>> lisi instanceof Person √ lisi是通过Person类new出的
        >>> lisi instanceof Object √ 所有对象都是Object的实例
        >>> Person instanceof Object √ 函数本身也是对象
 
6、广义对象与狭义对象:
    ① 狭义对象:只有属性和方法,除此之外没有任何其他内容。
                           var obj = {} var obj = new Object();
    ② 广义对象:除了用字面量声明的基本数据类型之外,JS中万物皆对象。换句话说,只要能够添加属性和方法的变量,都可以成为对象。
var s="123"; // 不是对象
s.name="aaa";
console.log(typeof s); // String
console.log(s.name); // Undefined 字面量声明的字符串不是对象,不能添加属性。
2. 成员属性、静态属性和私有属性

2.1成员属性与成员方法

在构造函数中,使用this.属性 声明,或者在实例化出对象以后,使用"对象.属性"追加的,都属于成员属性或成员方法,
也叫实例属性和实例方法。
 
成员属性/方法,是属于由类new出的对象的。
需要使用"对象名.属性名"调用
        var zhangsan = new Person("张三");
zhangsan.age = 14; // 追加成员属性
console.log(zhangsan.age); // 调用成员属性

2.2静态属性与静态方法

1、通过"类名.属性"、"类名.方法"声明的属性和方法,称为静态属性、静态方法,也叫类属性和类方法。
 
   类属性/类方法,是属于类的(属于构造函数的)
   通过"类名.属性名"调用
 
2、成员属性是属于实例化出的对象的,只能使用对象调用。
   静态属性是属于构造函数的,只能使用类名调用。
        Person.count = "60亿"; // 声明静态属性
console.log(Person.count); // 调用静态属性
var lisi = new Person("李四");
console.log(lisi.count); // Undefined 静态属性是属于类的,只能用类名调用

2.3私有属性与私有方法

在构造函数中,使用var声明的变量,称为私有属性;
在构造函数中,使用function声明的函数,称为私有方法;
             function Person(){
var num = 1; // 私有属性
function func(){}; // 私有方法
}

私有属性和私有方法的作用域,只在构造函数内部有效。即,只能在构造函数内部使用,无论使用对象名还是类名都无法调用。

3. JS模拟实现封装
 
1、 什么叫封装?
    ① 方法的封装:将类内部的函数进行私有化处理,不对外提供调用接口,无法在类外部使用的方法称为私有方法,即方法的封装。
 
    ② 属性的封装:将类中的属性进行私有化处理,对外不能直接使用对象名访问(私有属性)。同时,需要提供专门用于设置和读取私有
                              属性的set/get方法,让外部使用我们 提供的方法,对属性进行操作。这就叫属性的封装。
 
2、 注意:封装不是拒绝访问,而是限制访问。要求调用者,必须使用我们提供的set/get方法进行属性的操作,而不是直接拒绝操作。
                  因此,单纯的属性私有化,不能成为封装!必须私有化之后,提供对应的set/get方法
function Person(){
var age=0;
this.setAge=function(ages){
age=ages;
}
this.getAge=function(){
return age;
}
}
4. JS中的this指向详解

4.1谁最终调用函数,this就指向谁

4.1.1  this指向谁,不应该考虑函数在哪声明,而应该考虑函数在哪调用!!!
4.1.2  this指向的,永远只可能是对象,而不可能是函数!!!
4.1.3  this指向的对象,叫做函数的上下文/context,也叫函数的调用者
 

4.2this指向的规律!!!(与函数的调用方式息息相关)

4.2.1  通过函数名()调用的,this永远指向window  
 func();
 
4.2.2  通过对象.方法调用的,this指向这个对象
obj.func(); // 狭义对象
document.getElementById("div1").onclick = func; // 广义对象
 
4.2.3  函数作为数组中的一个元素,用数组下标调用的,this指向这个数组
var arr = [1,2,3,func,4,5,6];
arr[3]();
 
4.2.4  函数作为window内置函数的回调函数使用,this指向window。setInterval setTimeout 等
setTimeout(func,1000);
 
4.2.5  函数作为构造函数,使用new关键字调用,this指向新new出的对象。
var obj1 = new func();
5. 原型与原型链

5.1__proto__与prototype

5.1.1   prototype:函数的原型对象
     ① 只有函数才有prototype,而且所有函数必有prototype。
     ② prototype本身也是一个对象!
     ③ prototype指向了当前函数所在的引用地址!
 
5.1.2   __proto__:对象的原型!
     ① 只有对象才有__proto__,而且所有对象必有__proto__。
     ② __proto__也是一个对象,所以也有自己的__proto__,顺着这条线向上找的顺序,就是原型链。
     ③ 函数、数组都是对象,都有自己的__proto__
 
5.1.3   实例化一个类,拿到对象的原理?
      实例化一个类,实际上是将新对象的__proto__,指向构造函数所在的prototype。
      也就是说:zhangsan.__proto__==Person.prototype √
 
5.1.4   所有对象的__proto__沿原型链向上查找,都将指向Object的prototype。
      Object的prototype的__proto__,指向null
 

5.2原型链的指向问题

研究原型链的指向,就是要研究各种特殊对象的__proto__指向问题。
5.2.1   通过构造函数,new出的对象,新对象的__proto__指向构造函数的prototype
5.2.2   函数的__proto__,指向Function()的prototype
5.3.3   函数的prototype的__proto__指向Object的prototype
           (直接使用{}字面声明,或使用new Object拿到的对象的__proto__直接指向Object的prototype)
5.2.4   Object的prototype的__proto__指向null
           (Object作为一个函数,它的__proto__指向Function()的prototype)
 

6. 原型属性与原型方法
6.1   成员属性与成员方法:
   this.name = ""; this.func = function(){}
   >>> 属于实例化出的新对象,使用 对象.属性 调用
 
6.2   静态属性与静态方法:
   Person.name = ""; Person.func = function(){}
   >>> 属于类的,用 类名.属性 调用
 
6.3   私有属性与私有方法:
   构造函数中,使用var声明属性,使用function声明方法;
   >>> 只在类内部能够使用,外部无法使用任何方式调用。
 
6.4   原型属性与原型方法:
   Person.prototype.name = "";
   Person.prototype.func= function(){};
   >>> 将属性或方法写到类的prototype上,在实例化的时候,这些属性和方法就会进入
      到新对象的 __proto__上,就可以使用对象名调用
 
也就是说,1/4适用对象名访问,2使用类名访问,3只能在函数内部使用。
 
6.5   当访问对象的属性或方法时,会优先使用对象自身上的成员属性和成员方法。如果没
   有找到,则使用 __proto__上面的原型属性和原型方法。如果依然没有继续沿原型链
   查找,最后返回Undefined。
 
6.6   习惯上,我们会将属性写为成员属性,讲方法定义为原型方法:
    例如:

function Person(){
this.name = "张三"; // 成员属性
}
Person.prototype.say = function(){};
   原因:
   ① 原型属性在定义后不能改变,无法在实例化时进行赋值。所以属性不能使用原型
        属性。但是方法,写完以后基本不用改变,所以,方法可以使用原型方法。
   ② 实例化出对象后,属性全在对象上,方法全在原型上,结构清晰。
   ③ 使用for-in遍历对象时,会将属性和方法全部打印出来。而方法往往并不需要展
        示,那么将方法写在原型上,就可以使用hasOwnProperty将原型方法过滤掉。
   ④ 将方法写道prototype上,将更节省内存
   ⑤ 官方都这么写
 
6.7   通过prototype扩展系统内置函数的原型方法
/**
* 给数组添加一个遍历打印所有值的方法
*/
Array.prototype.eachAll = function(){
for (var i=0;i<this.length;i++) {
console.log(this[i]);
}
}
var arr = [1,2,3,4,5,6,7];
arr.eachAll();
7. for-in循环
for-in 循环主要用于遍历对象
for()中的格式:for(keys in zhangsan){}
 
keys表示obj对象的每一个键值对的键!所以循环中,需要使用obj[keys]来取到每一个的值
 
for-in循环,遍历时不只能读取对象自身上面的成员属性,也能沿原型链遍历出对象的原型属性。
所以,可以使用hasOwnProperty判断一个属性是不是对象自身上的属性。
zhangsan.hasOwnProperty(keys)==true 表示这个属性是对象的成员属性,而不是原型属性。
        function Person(){
this.name = "张三";
this.age = 14;
this.func1 = function(){

}
}
Person.prototype.name1 = "zhangsan";
Person.prototype.age1 = 15;
Person.prototype.func2 = function(){}; var zhangsan = new Person(); for(keys in zhangsan) {
if (zhangsan.hasOwnProperty(keys)) {
console.log(zhangsan[keys]);
}
}
8. 继承

8.1扩展Object实现继承

8.1.1   扩展Object实现继承
      ① 声明父类
   function Parent(){}
          声明子类
   function Son(){}
 
   ② 通过prototype给Object类添加一个扩展方法:
    Object.prototype.extend = function(parent){
    for(var i in parent){
     this[i]=parent[i];
    }
    }
 
   ③ 分别拿到父类对象和子类对象:
   var p = new Parent();
   var s = new Son();
   ④ 用子类对象,调用扩展方法,实现继承操作:
   s.extend(p);
8.1.2   实现继承的原理:
   通过循环将父类对象的所有属性和方法,全部赋给子类对象。关键点在于for-in循环,
   即使不扩展Object,也能通过简单的循环实现操作。
 
8.1.3   扩展Object继承的缺点:
   ① 无法通过一次实例化,直接拿到完整的子类对象,而需要先拿到父类对象和子类对象两个对象,再手动合并。
   ② 扩展Object的继承方法,也会保留在子类的对象上。
 

8.2使用原型实现继承

8.2.1   使用原型实现继承
   ① 定义父类
   function Parent(){}
    定义子类
   function Son(){}
 
   ② 将父类对象,赋值给子类的prototype
   Son.prototype = new Parent();
   ③ 拿到子类对象,就会将父类对象的所有属性和方法,添加到__proto__
   var s = new Son();
8.2.2   使用原型继承的原理:
   将父类对象,赋值给子类的prototype,那么父类对象的属性和方法就会出现在子类的
   prototype中,那么,实例化子类时,子类的prototype又会到子类对象的__proto__
   中,最 终,父类对象的属性和方法,会出现在子类对象的__proto__中。
 
8.2.3   这种继承的特点:
   ① 子类自身的所有属性,都是成员属性,父类继承过来的属性,都是原型属性
   ② 依然无法通过一步实例化拿到完整的子类对象。
 

8.3call/apply/bind实现继承

[call/bind/apply]
1、 三个函数的作用:通过函数名调用这三个函数,可以强行将函数中的this指定为某个对象
 
2、 三个函数的写法(区别):
  call写法:func.call(func的this指定的obj,func参数1,func参数2,...);
  apply写法:func.call(func的this指定的obj,[func参数1,func参数2,...]);
  bind写法:func.call(func的this指定的obj)(func参数1,func参数2,...);
 
3、 三个函数的唯一区别,在于接收func的参数列表的方式不同,除此之外,功能上没有任何差异!!!
 
[使用call/bind/apply实现继承]
1、 实现步骤:
  ① 定义父类
  function Parent(name){}
  ② 定义子类时,在子类中使用三个函数,调用父类,将父类函数中的this,指向位子类函数中的this:
    function Son(no,name){
this.no = no;
Parent.call(this,name);
}
  ③ 实例化子类时,将自动继承父类属性
  var s = new Son(12,"张三");
9. 闭包
 
[JS中的作用域]
1、 全局变量:函数外声明的变量,成为全局变量;
  局部变量:函数内部使用var声明的变量,称为局部变量;
 
  在JS中,只有函数作用域,没有块级作用域!!也就是说,if/for等有{}结构体,
  并不能具备自己的作用域
 
  所以,函数外部不能访问函数内部的局部变量(私有属性)。因为,函数内部的变量,在
  函数执行完毕以后,就会被释放掉。
 
2、 使用闭包,可以访问函数的私有变量!
  JS中,提供了一种"闭包"的概念:在函数内部,定义一个子函数,子函数可以访问父
  函数的私有变量。可以在子函数中进行操作,最后将子函数通过return返回
       function func1(){
var num = 1;
function func2(){
return num;
}
return func2;
}
var num = func1()();
3、 闭包的作用:
  ① 可以在函数外部访问函数的私有变量;
  ② 让函数内部的变量,可以始终存在于内存中,不会在函数完成后释放掉

JavaScriptOOP的更多相关文章

  1. 初识JavaScriptOOP(js面向对象)

    初识JavaScriptOOP(js面向对象) Javascript是一种基于对象(object-based)的语言, 你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言 ...

  2. 详解面向对象编程——JavaScriptOOP

        前  言 絮叨絮叨 学习了JS之后,不知道大家觉得怎们样呢? 今天我们就来讲一下JS中最重要的一个环节,JavaScript中的面向对象编程OOP,这里的东西有点难,也有点绕. 可是! 不要灰 ...

  3. javascript-OOP基础详解

      前  言 S     N 今天给大家详解一下面向对象编程(简称OOP)基础,OOP 语言使我们有能力定义自己的对象和变量类型 .对象拥有属性和方法 . 所以今天就给大家详解对象和类 . 1-1简介 ...

  4. 【JavaScript OPP基础】---新手必备

    今天和大家分享一下近期整理的有关JavaScriptOPP的基础知识~~~我们一起来学习一下-- JavaScriptOPP基础 一.面向对象编程OOP1.语言的分类:面向机器:汇编语言面向过程:C语 ...

  5. JavaScript模块化演变 CommonJs,AMD, CMD, UMD(一)

    原文链接:https://www.jianshu.com/p/33d53cce8237 原文系列2链接:https://www.jianshu.com/p/ad427d8879cb 前端完全手册: h ...

随机推荐

  1. none,hidden和opacity="0"设置元素不可见的区别

    none,hidden和opacity="0"均可设置元素为不可见的状态.其中none属于display的属性值,hidden属于visibility的属性值.使用none时元素不 ...

  2. java初阶

    java的开发工具分成 IDE(integrated developmentenvironment )和JDk(Java Development Kit) 一个.java中只能有一个public类且至 ...

  3. mysql 5.7 Warning: Using a password on the command line interface can be insecure. 解决方案

    百度了好多,发现都是lunix环境下的,没有找到windows和OS 的,在lunix环境下的解决方案一般就是修改数据库配置文件 my.conf 在Windows 中是没有my.cnf 文件,而是叫做 ...

  4. 24点游戏详细截图介绍以及原型、Alpha、Beta对比

    原型设计 图片展示 功能与界面设计 1.登录注册 2.手机号验证 3.24点游戏 4.粉色系女生界面 Alpha 图片展示 功能与界面设计 1.24点游戏 2.背景音乐 3.可查看多种可能的答案 4. ...

  5. Swing-JSlider用法-入门

    JSlider是Swing中的滑块控件,在交互过程中用户可拖动它来实现数值的调整.它具有3个基本参数,分别为:最小值.最大值和初始值,如果不指定数值,则默认值分别为:0,100,50.滑块的值发生改变 ...

  6. java--整理下关于static关键字的知识

    如果将域定义为static,每个类中只有一个这样的域.而每一个对象对于所有的实例域却都有自己的一份拷贝.--<java核心技术> 使用static的两种情形:1.只想为某特定域分配单一存储 ...

  7. 201521123038 《Java程序设计》 第八周学习总结

    201521123038 <Java程序设计> 第八周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 从集合里面获取对象时必须进行强制类 ...

  8. 201521123004《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 接口 接口(interface)就是方法声明和常量值的集合 实现接口的类叫接口的 ...

  9. 201521123030《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 控制可见性的4个访问修饰符 private -- 仅对本类可见 public -- 对所有类 ...

  10. linux (1)基本知识/目录/磁盘格式/文件系统

    一.linux基本知识介绍1.命令行格式:(按两次tab可以知道有多少个可执行命令,我的有1980个,用户有1960个)[用户名@linux主机名 ~(当前目录)]$ 命令 选项 参数1 参数2[ro ...