面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。它将真实世界的各种复杂的关系,抽象为一个个对象,然后由这些对象分工合作,完成对真实世界的模拟。所以,对象是个什么东东勒?
对象
我们可以用女娲造人来理解,女娲只有一个,但是她可以制作出各种各样的人,她制作出来的人就是我们说的一个个对象,每个人(对象)有相同的特点、行为,也有不同的。
那我们这些人身上的肤色,身高体重等等都是我们身上的属性,即对象的属性,我们会走、跑、吃饭、睡觉,这些行为就叫做方法,即对象的方法,我们这些东西哪来的,都是女娲造的,所以我们要用某一个属性或者方法,就要看女娲给我们捏了没有,没有就需要自己创建
构造函数
女娲就是我们说的模板,即构造函数。JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。
构造函数的特点,一是它本质就是普通的函数,和其他函数没有任何区别,但是构造函数名首字母习惯大写,便于区分,二是它创建对象的时候必须加上new关键字,如 var person = new Person();
new命令
new命令的作用,就是执行构造函数,返回一个实例对象,根据需要,构造函数后面的括号里面可以加上参数,对创建的对象的属性实例化,即创建对象的同时给对象的属性赋值。由于new本身就可以执行构造函数,所以构造函数后面的括号可加可不加,但是为了表示调用函数,建议加上。那么,加入忘记加new命令,会怎么办呢
不写new之后,后面就是一个普通函数执行,你想创建的对象只是函数执行后的结果而已
为了保证构造函数必须与new命令一起使用,一个解决办法是,构造函数内部使用严格模式,即第一行加上use strict。一旦忘了使用new命令,直接调用构造函数就会报错。
function f(x, y){
'use strict';
this._x = x;
this._y = y;
}
f()
// TypeError: Cannot set property '_x' of undefined
上面代码的Fubar为构造函数,use strict命令保证了该函数在严格模式下运行。由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错(JavaScript 不允许对undefined添加属性)。
另一个办法是函数内部判断是否是用来new命令,如果没用可以返回一个错误提示,或者直接返回一个空对象(需要用到instanceof,此处不做示例,后期讲instanceof)
new命令的原理
在函数的内部创建一个空对象(因为new命令会返回一个实例对象),将该空对象的原型指向构造函数的prototype属性,将空对象赋值给构造函数内部的this,然后执行构造函数内部的代码(即把这一部分放在构造函数的最上层),看代码:
function Person(name, height){
//var {}(此处用{}代替空对象) = Object.creat(Person.prototype);
//var this = {};
this.name = name;
this.hieght = height;
return {};
//return this;
}
var person1 = new Person(a,1);
var person2 = new Perosn(b,2);
//我们这个时候去访问person1和person2的话,就是一个空对象,显示的返回一个空对象{}就成捣乱了,但是其实是要返回this的
如果return返回的时候不是一个对象,那么就会忽略这个return
new.target
函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined。使用这个方法可以直接判断外部是否是用了new命令
function test(){
if(!new.target){
throw new Error("外部没有使用new命令");
}
console.log("创建对象,请使用new命令")
}
var s = test();
//ncaught Error:外部没有使用new命令
//创建对象,请使用new命令
有时候我们并没有构造函数,但是需要创建我们的对象时,需要用到Object.creat();方法
creat()括号中加入的就是我们需要使用的模板,看代码:var obj1 = {
a: 1,
b:2,
say:function (){
console.log("这是模板");
}
}
var obj2 = Object.creat(obj1);
//假如这里面的obj1是一个构造函数
//那么var obj2 = Object.creat(obj1);相当于var obj2 = new Obj1();
obj2继承了obj1的属性和方法