//经过字面量建立对象 var obj1 = { name:'Jack', age: 18 }
// 经过系统自带的构造函数构造对象 // 其余构造函数有:new Array(),new Number,new Date(),new Boolean() var obj2 = new Object(); obj2.name = 'Jack'; obj2.age = 18;
// 经过自定义函数构造对象 // 为了和普通函数区别,构造函数命名首字母要大写(帕斯卡命名法) function Obj3(name,age) { this.name = name; this.age = age; this.sayHi = function () { alert(this.name) }; } var dx1 = new Obj3('Jack', 18); var dx2 = new Obj3('Brush', 18);
首先,我先说下自定义构造函数建立对象的基本流程,使用new和不适用new差异很大,不用new的话,则Obj3(name)就做为一个普通的函数执行(只是函数名的首字母大写了),没有返回值,那么默认返回的是undefined,而用new关键字后,JS就会把该函数做为一个构造函数看待,通过一系列的隐式操做,返回值是一个对象了。函数
new关键字的“隐式操做”:this
①在内存中建立一个空的Object类型的对象----看不到spa
②让this关键字指向这个空的对象(将构造函数的做用域赋给新对象)----看不到prototype
// ① ② 的执行过程 var this = Object.creat(Obj3.prototype); // this 指向 Obj3.prototype(后面讲到) // 能够看出构造函数建立对象的最根本原理是借用Object.create()方法来实现的,只不过被封装功能化了
在前面的例子中,dx1和dx2分别保存着Obj3的一个不一样的实例。这俩个对象都有有一个constructor(构造函数)的属性,该属性指向Obj3,以下:设计
console.log(dx1.constructor == Obj3) // true console.log(dx2.constructor == Obj3) // true
对象的constructor属性最初用来表示对象类型的。可是,检测对象类型,仍是instanceof操做符要更可靠一些-----用来检测一个对象在其原型链中,是否存在一个构造函数的prototype属性。指针
咱们在这个例子中建立的全部对象即便Object的实例,同时也是Obj3的实例,这一点能够经过instanceof操做符能够获得验证。code
console.log(dx1 instanceof Obj3); // true console.log(dx1 instanceof Object); // true console.log(dx2 instanceof Obj3); // true console.log(dx2 instanceof Object); // true // dx1 和 dx2 之因此同时是Object的实例,是由于全部的对象均继承自Object
③经过this给这个对象添加属性和方法---看得见对象
// this.name = 'Jack'; this.age = 18;
④将这个对象返回给用new关键字调用的构造函数Obj3(name)的调用者(dx1)blog
return this;
继承
那么prototype就能够经过调用构造函数而建立的那个对象实例的原型对象。使用原型对象的好处是可让全部对象实例共享它所包含的属性和方法。换句话说,没必要在构造函数中第一对象实例的信息,而是能够将这些信息直接添加到原型对象中去,那么上面的Obj3()函数就能够写成这样:
function Obj3(name,age) { this.name = name; this.age = age; } Obj3.prototype.sayHi = function () { alert(this.name) } var dx1 = new Obj3('Jack', 18); var dx2 = new Obj3('Brush', 18);
当构造函数建立一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型方法。在每个对象都支持一个属性:"_ proto _"。
咱们能够经过isPrototype()方法来肯定对象之间是否存在这个关系。从本质上讲,若是[Prototype]指向调用isPrototype()方法的对象(Obj3.prototype),那么这个方法就返回true。(参考《JavaScript高级程序设计(第3版)》)
使用hasOwnProperty()能够检测一个属性是否存在在实例中,仍是存在在原型中。这个方法(从Object继承来的)只是给定属性存在在对象实例中,才会返回true;存在在原型中,返回false。
全部的原型应用类型(Object、Array、String)都在其构造函数的原型上定义了方法。在Array.prototype中能够找到sort()方法;在String.prototype中能够找到substring()方法,以下:
console.log(Array.prototype.sort); // ƒ sort() { [native code] } console.log(String.prototype.substring); // ƒ substring() { [native code] }
咱们知道,全部引用类型默认都继承了Object,而这个继承也是经过原型链实现的。全部函数的默认原型都是Object的实例,所以默认原型都包含一个内部指针,指向Object.prototype。这正是全部自定义类型都会继承toString()、valueOf()等默认方式的根本缘由。