一、面向对象

1. 面向对象 是所有语言 都有的一种编程思想,组织代码的一种形式

  • 基于对象的语言:JS语言
  • 面向对象的语言:c++ java c#

2. 面向对象 3大特征

封装:将重用代码封装到函数 / 对象中,实现代码复用
继承:继承方法、属性(JS通过原型实现继承、其他语言通过类实现继承)
多态:同一操作针对不同对象,表现出不同的行为(JS中没有多态)

3. 面向对象的优势

  • 模块化,便于维护:将功能相近的代码封装成一个的对象,有代码更改,只需找到对应的对象进行修改即可

  • 减少全局污染,只暴露出一个构造函数,需要的话 new 一个对象就可以

4. 分析 面向过程 、面向对象

  • 面向过程:

    • 所有的细节、步骤、过程,要一步一步亲历亲为(执行者)
    • 代码量少功能简单 的场景 适用
    • 代码执行效率高,创建的变量全局变量太多,环境污染严重(ES5)
  • 面向对象:

    • 把一些功能逻辑,赋予给一个个独立的对象,对象中封装了一些列方法
    • 找到能完成这个事情的对象,让它帮你完成就行(调度者)
    • 对于大型项目,有利于团队合作开发、有利于项目代码的维护扩展,项目更新迭代;
    • 代码执行效率较低;使用面向对象思想编程可能导致代码复杂度提高
    • JQ操作DOM就是一个面向对象的方式
  • 两者关联:面向对象是对面向过程的封装

二、JS 中实现继承的3种方式

1. 混入式继承for-in:遍历为新对象添加属性、方法

<script>var obj = {name: 'zhang',age: 11};var o2 = {};for (var key in obj) {o2[key] = obj[key];}console.log(o2);
</script>
  • js 原生语法:没有 类似JQ中的 extend() 方法,封装如下:
<script>var obj = {name: 'zhang',age: 11};var extend = function (obj) {var o2 = {};for (var key in obj) {o2[key] = obj[key];}return o2;}console.log(extend(obj));
</script>

2. Object.create() 继承 :ES5中; IE8及以下不兼容

  • Object.create(参数的对象) 返回新对象,继承了参数对象上的所有属性、方法
<script>var o1 = {name: 'zhangxin'};var create = Object.create(o1);console.log(create.name);  // 'zhangxin'
</script>

3. 原型继承:实例对象 继承自 原型对象的方法/属性 【重要】

三、构造函数

1. 概念:用于创建对象(对象初始化)的一种普通的函数,一般在 new 运算符后面调用

  • 构造函数名的第一个字母,约定大写;用于区分普通函数

  • new 的作用:

    • 申请内存,创建空对象
    • 改变this指向
    • 给新对象赋值
    • 返回新对象
  • 构造函数中this的作用:为对象添加成员(属性、方法)

  • 构造函数 与 普通函数的区别:

    • 函数内部this指向不同
    • 返回返回值不同

2. 函数一创建,就有了 prototype 属性,指向原型对象

  • Math 除外,Math 是对象,不是构造函数,没有 prototype 属性

3. 构造函数中的返回值

  • 构造函数中:一般不写返回值,默认返回新创建的对象

  • 若写了返回值:

    • 返回值为引用类型:忽略新创建的对象,直接返回引用类型的返回值
    • 返回值为基本类型:忽略基本类型,直接返回新创建的对象

4. 常见的构造函数,但 Math 不是构造函数

  • ObjectFunctionArrayStringNumberRegExpData 这些构造函数都有 prototype属性

  • Math 是对象,不是函数,没有 prototype 属性

5. 构造函数的作用:对new出来的函数,进行初始化(为属性、方法赋值)

四、实例(对象)

1. 对象一创建,就有了 __proto__ 属性,指向原型对象

  • 这个属性是浏览器私有属性,一般不常用

2. 对象( null除外) 在被创建的那一刻,原型就定下来了, 即: 对象.__proto__

  • 即使修改了 构造函数.prototype 的指向,也不会影响到 已经创建好的对象 的原型对象、原型链

  • 原型对象不会被默认改变,除非手动改变指针方向,即 对象.__proto__的指向

3. 任何对象 都直接 或 间接的继承自 Object.prototype

4. 实例化过程:即创建实例对象的过程,new 构造函数

五、原型(对象)

1. 理解原型:

  • 原型:用来存放一些公共的属性或方法,让多个实例对象 访问同一个对象中的内容

  • 作用:原型继承,节省内存,实现数据共享

2. 原型对象 默认有 constructor 属性,指当前的构造函数

  • 改变构造函数.prototype原型指针方向时,最好在新的原型对象上,添加 constructor 属性

3. 读取 原型对象 指针

  • 构造函数.prototype

  • 实例对象.__proto__ 【生产环境中不使用】

  • 两个属性的区别仅仅是:站在不同的角度访问同一个对象

4. 原型对象 添加属性、方法

  • 构造函数 . prototype . 属性/方法 =‘’;

  • 实例对象 . proto . 属性/方法 =‘’; 【一般不使用】

5. 顶级原型 Object.prototype , 万物皆对象

  • Objet.prototype = null

6. 顶级原型上的属性 —> 任何一个对象都能直接使用(对象本身有同名属性除外)

(1) Object.prototype.constructor 指向构造函数 Object
(2) Object.prototype.toString() 判断 当前变量 属于哪种 引用类型
  • Array / String / Number / Date 都有自己的 toString() 方法,即:转为字符串 ; 验证是属于哪个引用类型,可借用 顶级对象上的toString()方法
<script>console.log(Object.prototype.toString());               // [object Object]console.log(Math.toString());                           // [object Math]console.log(Object.prototype.toString.call([]));        // [object Array]console.log(Object.prototype.toString.call('aaa'));     // [object String]console.log(Object.prototype.toString.call(111));       // [object Number]console.log(Object.prototype.toString.call(new Date())); // [object Date]console.log(Object.prototype.toString.call(Array));     // [object Function]console.log(Object.prototype.toString.call(String));    // [object Function]console.log(Object.prototype.toString.call(Number));    // [object Function]console.log(Object.prototype.toString.call(Date));      // [object Function]
</script>
  • 对象在隐式转换时,调用 toString()方法
<script>var obj = {};console.log(obj + '222');  // [object Object]222
</script>
(3) Object.prototype.valueOf()
(4) Object.prototype.toLocaleString()
  • 转化为本地n的字符串
<script>var date = new Date();console.log(date);  // Sun Nov 12 2017 16:57:57 GMT+0800 (CST)console.log(date.toLocaleString()); // 2017/11/12 下午4:57:57
</script>
(5) 对象.hasOwnProperty("属性名") 判断该属性是不是对象本身提供的,返回布尔值
<script>var Fn = function () {this.name = 'zhangxin'}Fn.prototype = {age: 18};var obj = new Fn();var result1 = obj.hasOwnProperty('name');var result2 = obj.hasOwnProperty('age');console.log(result1);  // trueconsole.log(result2); // false
</script>
(6) 原型对象.isPrototypeOf(对象) 判断括号中对象是否在原型对象的原型链上,返回布尔值
<script>var arr = [];var result = Array.prototype.isPrototypeOf(arr);console.log(result);  // true
</script>
(7) 对象.properyIsEnumerable(属性名) 属性是否是对象自身的 且 可枚举(遍历)

六、原型链

1. 概念

  • 任何一个对象都有原型对象, 原型对象也是对象, 所以, 原型对象也有原型对象。 这样一直往上, 就形成了一条原型对象的链式结构, 我们把这个链式结构称为: 原型链。

  • 各个对象之间:通过 proto 连接起来,形成原型链

2. 常见的原型链

obj对象的原型链:obj  ---> Object.prototype  --->  null  【最短的原型链】arr数组的原型链:arr ---> Array.prototype  --->  Object.prototype  --->  nullfn函数的原型链:fn ---> Function.prototype ---> Object.prototype ---> nullstr字符串的原型链:str ---> String.prototype ---> Object.prototype ---> null

3. Objet.prototype = null;所以 Objet.prototype是原型链结构的最上层,即万物皆对象

定义一个对象,它的原型链 就确定下来了,不会再变

定义一个函数,它的作用域链 就确定下来了,不会再变

4. 原型链分析

  • 对象( null除外) 在被创建的那一刻,原型就定下来了, 即: 对象.__proto__ ; 即使改变构造函数.prototype的指向,也不会改变已创建好对象的原型链

  • 已创建好的对象,若想改变它的原型链,设置构造函数.prototype的指向 不管用;需要设置对象.__proto__ 指向

  • in 运算符 判断的是:属性是否在 对象的原型链上

5. 完整原型链

5. 属性搜索原则 沿着 原型链 进行搜索

  • 读取: 属性延原型链,一级一级向上找,一直查找到 Object.prototype 对象;属性找不到undefined;方法找不到,找不到的话报错

  • 实例对象 可以直接访问 原型对象的所有属性和方法,因为对象继承 自 原型对象。

6. 类比 变量搜索原则

  • 读取: 变量延作用域链查找声明,一级一级向外找,首先在当前作用域找声明,若没有就到n-1级链查找,直到找到0级链(全局变量);找不到 就报错,因为未声明的变量

七、JS面向对象编程 —> 【原型继承】

1. 基于原型链重新理解 原型继承:(实例对象 继承自 原型对象的方法/属性)

  • 任何对象都有一条原型链存在,所谓的原型继承就是通过任何手段,改变原型链的层次结构(即:构造函数.prototype 的指向),对象通过访问原型链中的属性或者方法,从而实现继承。

  • 应用了:实例对象可以直接访问原型对象中的属性、方法

2. 面向对象编程, 最佳实践:

  • 将对象的大部分属性:放到构造函数中

  • 将对象的所有方法、公共属性:放到原形对象中

  • 构造函数中属性复用,原型对象中方法继承

  • 通过 new 构造函数 创建的对象,实例对象 继承自原型对象上的属性 / 方法

3. 理解面向对象编程

  • 面向对象编程是根据功能,将代码拆解为一个个独立的功能体;

  • 独立的功能体 即 模块,模块化编程,降低了耦合度;较少全局污染;

  • 一般情况下一个单独个体封装在一个JS文件中,JS文件中值暴露出一个构造函数

  • 引入JS文件,模块外部,需要这个功能体时,new 构造函数 即可

(function(window) {var Bird = function(options) {this.name = options.name;this.age = options.age;};Bird.prototype = {constructor: Bird,action() {console.log(this.name);console.log(age);}};window.Bird = Bird;
})(window);

八、instanceof — 被检测对象是否在 构造函数的原型链上

  • 语法:被检测对象 instanceof 构造函数 返回布尔值

  • 可类比:原型对象.isPrototypeOf(对象) 判断括号中对象是否在原型对象的原型链上,返回布尔值

  • 作用:

    • 检测 对象是否在构造函数的原型链上
    • 检测 数组
  • 规律:

    • 创建对象后:修改 构造函数.prototype的值, 检测表达式 返回 false
    • 创建对象后:不修改 构造函数.prototype的值, 检测表达式 返回 true
  • 任何对象 instanceof Object 值都是 true

<script>var Person = function () {}var a = new Person();Person.prototype = {};console.log(a instanceof Person);  // falseconsole.log(Person.prototype.isPrototypeOf(a));   // false// 此时:a的原型链: a --- {} --- Object.prototype --- null
</script>

九、in — 判断 属性是否在对象的原型链上

<script>var Fn = function () {this.name = 'zhang';}Fn.prototype.age = 19;var obj = new Fn();console.log('name' in obj);     // trueconsole.log('age' in obj);      // true
</script>
  • 任何一个未声明的变量,都在 window的原型链上
console.log('a' in window); // true

十、delete — 删除 对象上的属性

<script>var obj = {name: 'zhangxi',age: 18};delete obj.age;console.log(obj);  // {name: 'zhangxi'}
</script>

十、静态成员 、 实例成员

成员:属性 和 方法

私有/静态成员

  • 由构造函数直接能够访问到的,跟构造函数相关的属性和方法。

共有/实例成员

  • 由实例对象直接访问到的,与实例对象向关联的属性和方法。

最佳实践

  • 如果静态成员、实例成员中有一个功能相似的方法,将逻辑代码放到静态成员中,实例成员只需调用静态成员的方法即可使用!
  • $ 或 jQuery,在jQuery库中可以被看作是 构造函数,其后跟的方法,静态成员!

  • $() 这个方法的返回值就是:jQuery对象(jQuery的实例对象),其后跟的方法,实例成员!

each 方法由两种使用方式:
$('div').each(function(index,value) {});   实例成员
$.each(arr,function(index,value) {});     静态成员 $.ajax()

十一、易混知识点

1. Function 是JS中的一等公民,自生;在原型链中即作为对象,又作为函数

2. Function: Function创造 Object 和 function

3. 构造函数的类型:function;【特殊】:Math 是对象,不是构造函数,其类型object

4. 构造函数的原型的类型:object;【特殊】:Function.prototype 的类型为function

5. 引用类型的 类型:object;【特殊】:function fn() {} 的类型为function

5. null 不是对象,但位于原型链的最顶层; 通常用 null 来代表一个空对象

JS 面向对象编程、原型链、原型继承(个人学习总结)相关推荐

  1. 简单粗暴地理解js原型链–js面向对象编程

    简单粗暴地理解js原型链–js面向对象编程 作者:茄果 链接:http://www.cnblogs.com/qieguo/archive/2016/05/03/5451626.html 原型链理解起来 ...

  2. 简单粗暴地理解js原型链--js面向对象编程

    原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧, ...

  3. 深入理解原型链与继承(详解JS继承原理)

    文章目录 原型链与继承 new 关键字的执行过程 构造函数.实例对象和原型对象 原型链的概念及图解 第一层`__proto__`指向:实例对象 第二层`__proto__`指向:`Function.p ...

  4. js原型和原型链_初识JS原型/原型链/原型继承

    本文思路: 原型->原型链->原型继承->基于原型的继承/ES6中的继承->__proto__与prototype 首先我们知道JS中有对象,比如: var 但是在我们没有对这 ...

  5. 详解JS原型链与继承

    详解JS原型链与继承 JavaScript 目录 摘自JavaScript高级程序设计: 概念 确定原型和实例的关系 原型链的问题 借用构造函数 组合继承 原型继承 寄生式继承 寄生组合式继承 new ...

  6. JS原型和原型链、继承

    前置 在JavaScript中,对象分为2种,一种是普通对象,另外一种是函数对象. 所有的对象都有__proto__属性,但是只有函数对象有prototype属性.函数对象,其实就是 JavaScri ...

  7. JS基于原型链的继承和基于类的继承学习总结

    1. new关键字创建一个对象的过程 (1) 创建一个空的简单对象(即{}) (2)为步骤1新创建的对象添加属性_proto_,该属性连接至构造函数的原型对象 (3)将步骤1新创建的对象作为this的 ...

  8. 原型和原型链原型继承_我如何看待Flash的教训,拥有原型的未来

    原型和原型链原型继承 Prototyping is critical part of UX process. Obviously, prototyping tools play significant ...

  9. JavaScript 原型链和继承面试题

    JavaScript 原型链和继承问题 JavaScript 中没有类的概念的,主要通过原型链来实现继承.通常情况下,继承意味着复制操作,然而 JavaScript默认并不会复制对象的属性,相反,Ja ...

最新文章

  1. Microbiome:植物发育和氮肥共同作用下的小麦根系微生物组
  2. LCCL网络:相互指导博弈来提升目标检测精度(附源代码)
  3. input.get_shape()的用法
  4. iOS之深入解析预乘透明度Premultiplied Alpha
  5. 如何解决JavaScript中0.1+0.2不等于0.3
  6. 螺钉装弹垫平垫机器人_【经验总结】什么时候用平垫,什么时候用弹垫?
  7. 【Flink】Flink 如何在本地IDEA恢复检查点 不通过IDEA 不通过 flink run 方法
  8. wordpress页面里可不可以写php,WordPress开发中如何在html中包含php
  9. 博为峰Java技术文章 ——JavaSE Swing JInternalFrame内部窗体面板II
  10. MySQL 命令无效问题
  11. 服务器客户端证书,使用服务器和客户端证书以及私钥创建SSLContext
  12. Android接入TapTap踩坑
  13. UnityEngine.Quaternion.LookRotation的使用(感觉这个用着还不错做一个笔记)
  14. 高手UI设计师干货总结分享品牌LOGO设计的过程要求及方法
  15. Linux:配置本地yum源仓库
  16. ORA-01652(永久表空间临时段不能扩展情况分析)
  17. 微纳制造技术 (上课)
  18. Vert.x ——概述
  19. 小米4可以刷入linux,给小米4刷上SailfishOS是怎样的体验?附刷机教程
  20. 硬汉内贾德:让美国人战栗(推荐)

热门文章

  1. python: float64与float32转换、压缩比较与转换偏差
  2. 电商入门:高手怎么去应用QQ云控引流轻松月入十万?
  3. (胡闹) RISC CSDN
  4. redis001-介绍+数据类型+5+3
  5. 项目开发SOP前端执行SOP
  6. 数字孪生城市研究案例
  7. 设置文本框 input [type=text] 的长度不超过固定值,输入的字符不超过固定值
  8. 第一章 ADG基本知识
  9. Mybatis中用@Select传参数
  10. 如何在一个月内写完论文?