new 关键字
new 在执行时会做四件事
- 在内存中创建一个新的空对象
- 让
this指向这个新的对象 - 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要
return)
构造函数和原型
构造函数
- JavaScript 的构造函数中可以添加以下成员,可以在构造函数本身上添加,也可以在构造函数内部的 this 上添加。
- 通过这两种方式添加的成员,分别成为
静态成员和实例成员- 实例成员:在构造函数内部创建的对象称为
实例成员,只能由实例化的对象来访问 - 静态成员:在构造函数本身上添加的成员称为
静态成员,只能由构造函数本身来访问
- 实例成员:在构造函数内部创建的对象称为
构造函数原型 prototype
- 构造函数通过原型分配的函数是所有对象
共享的 - JavaScript 规定,
每一个构造函数都有一个 prototype 属性,指向另一个对象。注意这个 prototype 就是就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有 - 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法
对象原型 __proto__
对象都会有一个属性 __proto__指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有__proto__原型对象的存在__proto__对象原型和原型对象prototype是等价的
new Star(){}
let ldh = new Star()
Star.prototype === ldh.__protot__ // true
__proto__对象原型的意义就在于为对象的查找机制提供一个方法,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype
constructor 构造函数
对象原型(__proto__)和构造函数(prototype)原型对象里面都有一个属性constructor属性,contructor 我们称为构造函数,因为它指回构造函数本身- constructor 主要用于记录该对象引用与哪个构造函数,它可以让原型对象重新指向原来的构造函数
- 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用 constructor 指回原来的构造函数
构造函数、实例、原型对象 三角关系
- 每一个函数都有一个
prototype属性,指向另一个对象 - 每个对象都会有一个
__proto__属性,指向构造函数的prototype原型对象 Student.prototype === Jane.__proto__prototype和__proto__指向的其实是同一个对象- 这个对象里有一个
constructor属性,指回构造函数本身 - 图中,
__proto__的连续指向,构成了原型链。当需要按照原型链查找时,其实就是沿着__proto__去查找
原型对象的 this 指向
- 在构造函数中,里面的 this 指向的是
对象实例 - 原型对象函数里面的 this 指向的是
实例对象
ES5 实现继承
-
ES6 之前并没有给我们提供
extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承- 借用构造函数继承父类型属性
- 核心原理:通过
call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性
- 核心原理:通过
- 借用原型对象继承父类型方法
- 核心原理:将父构造函数 new 出的实例 (
new Father())赋值给子构造函数的原型对象,并且将子构造函数的原型对象中的constructor指回原来的构造函数(子构造函数)
- 核心原理:将父构造函数 new 出的实例 (
- 借用构造函数继承父类型属性
图解 ES5 的继承
类的本质
- class 本质还是
function - 类的所有方法都定义在类的
prototype属性上 - 类创建的实例,里面也有
__proto__指向类的prototype原型对象 - 所以 ES6 的类它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
- 所以 ES6 的类其实就是
语法糖 语法糖:语法糖就是一种便捷写法,简单理解,有两种方法可以实现同样的功能,但是一种写法更加清晰、方便,那么这个方法就是语法糖
ES6 之前通过
构造函数+原型实现面向对象编程
ES6 通过类实现面向对象编程
内置对象
内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)- JavaScript 提供了多个内置对象:
Math、Date、Array、String等
Math
Math.PI // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值
Math.max() / Math.min() // 求最大和最小值
Date
- 获得 Date 总的毫秒数(时间戳),就是我们现在的时间,距离 1970.1.1 总的毫秒数
- 通过
valueOf(),getTime()
var date = new Date(); console.log(date.valueOf()); console.log(date.getTime())- 简单的写法
var date1 = +new Date();- H5 新增的方法
console.log(Date.now()); - 通过
Array
- 监测是否为数组
instanceof运算符,它可以用来监测是否为数组
var arr = []; var obj = {}; console.log(arr instanceof Array); console.log(obj instanceof Array);Array.isArray(参数),H5 新增的方法,ie9 以上版本支持
console.log(Array.isArray(arr)); console.log(Array.isArray(obj)); - 数组排序(冒泡排序)
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b) {
return a - b; // 升序的顺序排列
// return b - a; // 降序的顺序排列
})
String
- 根据位置返回字符
charAt(index)- 返回指定位置的字符(index 字符串的索引号)charCodeAt(index)- 获取指定位置处字符的 ASCII 码(index 索引号)str[index]- 获取指定位置处字符
- 截取字符串
substr(start, length)- 从 start 位置开始(索引号),length 取的个数slice(start, end)- 从 start 位置开始,截取到 end 位置,end 取不到(他们俩都是索引号)substring(start, end)- 从 start 位置开始,截取到 end 位置,end 取不到
堆和栈
- 栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。
简单数据类型存放到栈里面 - 堆:存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
注意:JavaScript 中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言