持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
构造函数
如果我们构建一个正方形,并且边长为5,6,5,6,求出它的面积和边长,可以这样写:
let squareList = [];
let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6];
for (i = 0; i < widthList.length; i++) {
squareList[i] = {
width: widthList[i],
getArea() {
return this.width * this.width;
},
getLength() {
return this.width * 4;
},
};
}
但是这样写会有一个问题,那就是每创建一个squareList,就需要在堆里开辟一个新的内存,然后getArea与getLeng同时也要各占用一个新的内存,那么就会创建24个重复的函数。如果创建12个squareList就需要开辟36个内存空间,且加上squareList本身的空数组占用的空间,以及widthList数组占用的空间,就需要38个内存空间。
如果把函数放到squareList的原型中呢?我们可以这样写:
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 (i = 0; i < widthList.length; i++) {
squareList[i] = Object.create(squarePrototype);
squareList[i].width = widthList[i];
}
但这种写法又太分散,怎么办?
函数和原型的结合:
let squareList = [];
let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6];
function createSquare() {
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 (i = 0; i < widthList.length; i++) {
squareList[i] = createSquare(widthList[i]);
}
这样写即把原型放在了函数上,又将函数放在原型内。
New操作符
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 < widthList.length; i++) {
squareList[i] = new Square(widthList[i]);
console.log(squareList[i].constructor);
}
new X()自动做了四件事情
- 自动创建空对象
- 自动为创建的空对象关联原型,原型地址指定为X.prototype
- 自动将空对象作为this关键字运行构造函数
- 自动return this
构造函数X
- X函数本身负责给对象本身添加属性。
- X.prototype对象负责保存对象的共有属性。
对象分类的理由
理由一
有很多对象拥有一样的属性和行为
需要把他们分为同一类
如square1和square2
这样创建类似对象的时候就很方便
理由二
但是也有很多对象拥有其他的属性和行为
所以就需要不同的分类
比如Square/Circle/Rect就是不同的分类
Array和Function也是不同的分类
数组对象
定义一个数组
let arr = [1,2,3]let arr = new Array(1,2,3) //元素为1,2,3let arr = new Array(3) //长度为3数组对象的自身属性- '0'/'1'/'2'/'3'/'length'
注意,属性名没有数字,只有字符串。
数组对象的共有属性 'push'/'pop'/'shift'/'unshift'/'join'
函数对象
定义一个函数
function fn(x,y){return x+y}let fn2 = function fn(x,y){return x+y}let fn=(x,y)=>x+ylet fn = new Function('x','y','return x+y')函数对象的自身属性
'name'/'length'
函数对象的共有属性
'call'/'apply'/'bind'
window 是谁构造的
Window
可以通过 constructor 属性看出构造者
window.Object 是谁构造的
window.Function
因为所有函数都是 window.Function 构造的
window.Function 是谁构造的
window.Function
因为所有函数都是 window.Function 构造的
浏览器构造了 Function,然后指定它的构造者是自己