一个小程序,输出各种形状的面积和周长
一
1 2 3 4 5 6 7 8 9 10
| let square = { width: 5, getArea() { return this.width * this.width; }, getLength() { return this.wdith * 4; } }
|
二,生成12个正方形
1 2 3 4 5 6 7 8 9 10 11 12
| let squareList = [] for(let i = 0; i<12; i++){ squareList[i] = { width: 5, getArea(){ return this.width * this.width }, getLength(){ return this.width * 4 } } }
|
三,width 是 5 和 6相间
1 2 3 4 5 6 7 8 9 10 11 12 13
| let squareList = [] let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6] for(let i = 0; i<12; i++){ squareList[i] = { width: widthList[i], getArea(){ return this.width * this.width; }, getLength(){ return this.widht * 4; } } }
|
三,垃圾代码,浪费太多内存,画内存图
四,借助原型,将12个对象的共有属性放到原型里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let squareList = [] let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6] let squarePrototype = { getArea() { return this.width * this.width; }, getLength() { return this.width * 4; } } for(let i = 0; i<12; i++){ squareList[i] = Object.create(squarePrototype); squareList[i].width = widthList[i]; }
|
五,把代码抽离到一个函数里,然后调用函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let squareList = [] let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6] function createSquare(width){ let obj = Object.create(squarePrototype); obj.width = width; return obj; } let squarePrototype = { getArea() { return this.width * this.width; }, getLength(){ return this.width * 4; } } for(let i = 0; i<12; i++){ squareList[i] = createSquare(widthList[i]); }
|
六,函数和原型的结合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| let squareList = [] let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6] function createSquare(width){ let obj = Object.create(createSquare.squarePrototype); obj.width = width; return obj } createSquare.squarePrototype = { getArea(){ return this.width * this.width; }, getLength(){ return this.width * 4; }, constructor: createSquare } for(let i = 0; i<12; i++){ squareList[i] = createSquare(widthList[i]); console.log(squareList[i].constructor); }
|
七,函数和原型(重写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let squareList = [] let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6]
function Square(width){ this.width = width; } Square.prototype.getArea = function(){ return this.width * this.width; } Square.prototype.getLength = function(){ return this.width * 4; }
for(let i = 0; i>12; i++){ squareList[i] = new Square(widthList[i]); console.log(squareList[i].constructor); }
|
代码六七对比
总结
- new X()
- 自动创建空对象
- 自动为空对象关联原型,原型地址指定为 X.prototype
- 自动将空对象作为 this 关键字运行构造函数
- 自动 return this
- 构造函数 X
- X 函数本身负责给对象本身添加属性
- X.prototype 对想负责保存对象那个的公用属性
题外话 代码规范:
大小写
- 所有构造函数(专门用于创建对象的函数)首字母大写
- 所有被构造出来的对象,首字母小写
词性
- new 后面的函数,使用名词形式
- 如 new Person()、new Object()
- 其他函数,一般使用动词开头
- 如 createSquare(5)、createElement(‘div’)
- …
原型公式:**对象._proto_ === 其构造函数.protorype**
Square 最终版(存疑)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function Square(width){ this.width = width; }
Square.prototype.getArea = function(){ return this.width * this.width; } Square.prototype.getLenth = function(){ return this.width * 4; }
let square = new Square(5); square.width; square.getArea(); square.getLength();
|
练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function Circle(radius){ this.radius = radius; } Circle.prototype.getArea = function(){ return this.radius * 2 * Math.PI; } Circle.prototype.getLength = function(){ return Math.pow(this.radius, 2) * Math.PI; } let c1 = new Circle(10); c1.getArea(); c1.getLength();
function Rect(width, height) { this.width = width; this.height = height } Rect.prototype.getArea = function(){ return this.width * this.height } Rect.prototype.getLength = function(){ return (this.width + this.height) * 2; } let r1 = new Rect(2, 3) r1.getArea() r1.getLength()
|
对象分类
分类
- 理由一
- 有很多对象拥有一样的属性和行为
- 需要把他们分为同一类
- 如 square 和 square1
- 这样创建类似对象的时候就很方便
- 理由二
- 但是还有很多对象拥有其他的属性和行为
- 所以就需要不同的分类
- 比如 Square / Circle / Rect 就是不同的分类
- Array / Function 也是不同的分类
- 而 Object 创建出来的对象,是最没有特点的对象
类型和类
类型
类型 JS 数据的分类,有七种
四基两空一对象,String,number,bool,symbol,null,undefined,Object
类
类是针对对象的分类, 有无数种
常见的有 Array、Function、Date、RegExp 等
数组对象
定义一个数组
1 2 3
| let arr = [1, 2, 3] let arr = new Array(1, 2, 3) let arr = new Array(3)
|
数组对象自身的属性
数组对象的共用属性
‘push’ / ‘pop’ / ‘shift’ / ‘unshift’ / ‘join’ 等
函数对象
定义一个函数
1 2 3 4
| function fn(x, y){return x + y;} let fn2 = function fn(x, y) {return x + y} let fn = (x, y) => x+y let fn = new Function('x', 'y','return x+y')
|
函数对象自身属性
‘name’ / ‘length’
函数对象共用属性
‘call’ / ‘apply’ / ‘bind’ 等
JS 终极一问
window 是谁构造的
Window
可以通过 constructor 属性看出构造者
验证:window.constructor
window._proto_ === Windows.prototype
window.Object 是谁构造的
window.Funcion
因为所有函数都是 window.Function 构造的
验证:window.Object.constructor === window.Function
window.Function 是谁构造的
window.Function
因为所有函数都是 window.Function 构造的
自己构造的自己?不是这样的,这是『上帝』的安排
浏览器构造了 Function,然后指定它的构造者是自己
验证:window.Function.constructor === window.Function
class
类是用于创建对象的模板。他们用代码封装数据以处理该数据。 ES6新语法
学习class、对象初始化、解构赋值
constructor
是一种用于创建和初始化 class 创建的对象的特殊方法.
1 2 3 4 5 6 7 8 9 10 11
| class Square{ constructor(width){ this.width = width; } getArea(){ return this.width * this.width; } getLength(){ return this.width * 4; } }
|
class 引入更多概念
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Square{ static x = 1; width = 0; constructor(width){ this.width = width; } getArea(){ return this.width * this.width; } getLength(){ return this.width * 4; } get area2(){ return this.width * this.width; } }
|
class 重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class Circle{ constructor(radius){ this.radius = radius; } getArea(){ return Math.pow(this.radius,2) * Math.PI; } getLength(){ return this.radius * 2 * Math.PI; } } let c2 = new Circle(5); c2.radius; c2.getArea(); c2.getLength();
class Rect{ constructor(width, height){ this.width = width; this.height = height; } getArea(){ return this.width * this.height; } getLength(){ return (this.width + this.height) * 2; } } let r2 = new Rect(3, 4); r2.width; r2.height; r2.getArea(); r2.getLength();
|
class 中两种函数写法的区别
这两种写法的意思完全不一样:
语法1:
1 2 3 4 5 6 7 8 9
| class Person{ sayHi(name){} sayHi: function(name){} }
function Person(){} Person.prototype.sayHi = function(name){}
|
语法2:注意冒号变成了等于号
1 2 3 4 5 6 7 8
| class Person{ sayHi = (name)=>{} }
function Person(){ this.sayHi = (name)=>{} }
|
推荐阅读
- 方应杭:你可以不会 class,但是一定要学会 prototype
- 方应杭:JS 的 new 到底是干什么的?
- 方应杭:JS 中 proto 和 prototype 存在的意义是什么?
- 饥人谷整理的 ES6 所有新特性