-
前言
- 0. 前端工具
- 1. html
- 2. CSS
-
3. JavaScript 基础
-
3.1 JS简介
-
3.2 变量
-
3.3 变量的强制类型转换
-
3.4 运算符
-
3.5 流程控制语句:选择结构(if和switch)
-
3.6 流程控制语句:循环结构(for和while)
-
3.7 对象简介和对象的基本操作
-
3.8 基本数据类型vs引用数据类型
-
3.9 函数
-
3.10 作用域
-
3.11 this
-
3.12 对象的创建&构造函数
-
3.13 原型对象
-
3.14 数组简介
-
3.15 数组的四个基本方法&数组的遍历
-
3.16 数组的常见方法
-
3.17 数组的其他方法
-
3.18 内置对象:Date
-
3.19 内置对象(其他)
-
3.20 DOM操作
-
3.21 事件对象Event和冒泡
-
3.22 事件委托
-
3.23 BOM的常见内置方法和内置对象
-
3.24 原型链
-
3.25 常见代码解读
-
3.1 JS简介
- 4. JavaScript进阶
- 5. 前端基本功:CSS、DOM练习和 Javascript 特效
- 6. jQuery
- 7. HTML5和CSS3
- 8. 移动web开发
- 9. Ajax
- 10. Node.js和模块化
- 11. ES6
- 12. Vue基础
- 13. React基础
-
14. 前端面试
-
14.1 准备
-
14.2 页面布局
-
14.3 CSS盒模型及BFC
-
14.4 DOM事件的总结
-
14.5 HTTP协议
-
14.6 创建对象和原型链
-
14.7 面向对象:类的定义和继承的几种方式
-
14.8 跨域通信类
-
14.9 安全问题:CSRF和XSS
-
14.10 算法问题
-
14.11 浏览器渲染机制
-
14.12 js运行机制:异步和单线程
-
14.13 页面性能优化
-
14.14 前端错误监控
-
14.15 JavaScript高级面试:前言
-
14.16 模块化的使用和编译环境
-
14.17 ES6
-
14.18 虚拟DOM
-
14.19 MVVM
-
14.20 面试题整理
-
14.21 网友面经
-
14.22 面试技巧
-
14.23 推荐文章
-
14.24 计算机网络
-
14.25 web安全
-
14.26 其他
-
14.1 准备
- 15. 面试题积累
- 16. 前端进阶
- 17. 前端综合
- 18. 推荐链接
前言
面向对象的三大特性
封装
继承
多态
原型链的知识
原型链是面向对象的基础,是非常重要的部分。有以下几种知识:
创建对象有几种方法
原型、构造函数、实例、原型链
instanceof
的原理new 运算符
创建对象有几种方法
方式一:字面量
var obj11 = {name: 'qianguyihao'};
var obj12 = new Object(name: 'qianguyihao'); //内置对象(内置的构造函数)
copy
上面的两种写法,效果是一样的。因为,第一种写法,obj11
会指向Object
。
第一种写法是:字面量的方式。
第二种写法是:内置的构造函数
方式二:通过构造函数
var M = function (name) {
this.name = name;
}
var obj3 = new M('smyhvae');
copy
方法三:Object.create
var p = {name:'smyhvae'};
var obj3 = Object.create(p); //此方法创建的对象,是用原型链连接的
copy
第三种方法,很少有人能说出来。这种方式里,obj3是实例,p是obj3的原型(name是p原型里的属性),构造函数是Objecet
。
原型、构造函数、实例,以及原型链
PS:任何一个函数,如果在前面加了new,那就是构造函数。
原型、构造函数、实例三者之间的关系
1、构造函数通过 new 生成实例
2、构造函数也是函数,构造函数的
prototype
指向原型。(所有的函数有prototype
属性,但实例没有prototype
属性)3、原型对象中有 constructor,指向该原型的构造函数。
上面的三行,代码演示:
var Foo = function (name) {
this.name = name;
}
var foo = new Foo('smyhvae');
copy
上面的代码中,Foo.prototype.constructor === Foo
的结果是true
:
- 4、实例的
__proto__
指向原型。也就是说,foo.__proto__ === Foo.prototype
。
声明:所有的引用类型(数组、对象、函数)都有__proto__
这个属性。
Foo.__proto__ === Function.prototype
的结果为true,说明Foo这个普通的函数,是Function构造函数的一个实例。
原型链
原型链的基本原理:任何一个实例,通过原型链,找到它上面的原型,该原型对象中的方法和属性,可以被所有的原型实例共享。
Object是原型链的顶端。
原型可以起到继承的作用。原型里的方法都可以被不同的实例共享:
//给Foo的原型添加 say 函数
Foo.prototype.say = function () {
console.log('');
}
copy
原型链的关键:在访问一个实例的时候,如果实例本身没找到此方法或属性,就往原型上找。如果还是找不到,继续往上一级的原型上找。
instanceof
的原理
instanceof
的作用:用于判断实例属于哪个构造函数。
instanceof
的原理:判断实例对象的__proto__
属性,和构造函数的prototype
属性,是否为同一个引用(是否指向同一个地址)。
注意1:虽然说,实例是由构造函数 new 出来的,但是实例的__proto__
属性引用的是构造函数的prototype
。也就是说,实例的__proto__
属性与构造函数本身无关。
注意2:在原型链上,原型的上面可能还会有原型,以此类推往上走,继续找__proto__
属性。这条链上如果能找到, instanceof 的返回结果也是 true。
比如说:
foo instance of Foo
的结果为true,因为foo.__proto__ === Foo.prototype
为true。foo instance of Objecet
的结果也为true,因为Foo.prototype.__proto__ === Object.prototype
为true。
但我们不能轻易的说:foo 一定是 由Object创建的实例
。这句话是错误的。我们来看下一个问题就明白了。
分析一个问题
问题:已知A继承了B,B继承了C。怎么判断 a 是由A直接生成的实例,还是B直接生成的实例呢?还是C直接生成的实例呢?
分析:这就要用到原型的constructor
属性了。
foo.__proto__.constructor === Foo
的结果为true,但是foo.__proto__.constructor === Object
的结果为false。
所以,用 consturctor判断就比用 instanceof判断,更为严谨。
new 运算符
当new Foo()时发生了什么:
(1)创建一个新的空对象实例。
(2)将此空对象的隐式原型指向其构造函数的显示原型。
(3)执行构造函数(传入相应的参数,如果没有参数就不用传),同时 this 指向这个新实例。
(4)如果返回值是一个新对象,那么直接返回该对象;如果无返回值或者返回一个非对象值,那么就将步骤(1)创建的对象返回。
参考《JS高程》6.2.2
类继承和原型继承的区别
copy