先贴出一个网上的例子:数组
function New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);复制代码
是否是看的不是很明白呢??别着急,我带你一点点深刻!!bash
var name = 'globalName'; //定义一个全局name
var obj = {
name: 'objName'
}
var foo = {
name: 'fooName',
getName: function() {
return this.name;
}
}
console.log(foo.getName()) // fooName
console.log(foo.getName.apply(obj)); // objName
console.log(foo.getName.apply()) // globalName
console.log(foo.getName.apply(window)) // globalName
console.log(foo.getName()) // fooName
console.log(foo.getName.call(obj)); // objName
console.log(foo.getName.call()) // globalName
console.log(foo.getName.call(window)) // globalName
复制代码
foo.getName()
//这里foo调用本身的方法,返回自身name属性值fooName,若是你们对于this指向还不清楚,请自行补课复制代码
foo.getName.apply(obj)
//这里经过使用apply方法切换getName函数执行的上下文环境,将this指向了obj,因此输出了objName,有一种借壳生蛋的做用复制代码
foo.getName.apply()
//这里在调用apply并无传入须要指向的参数,默认全局window对象复制代码
foo.getName.apply(window)
//这里显示的传入window对象,将this指向了window,输出了globalName复制代码
相信你们已经明白了apply的用法,call也是一样的道理,这里咱们只用到了apply和call方法的第一个参数,咱们再看看他们第一个参数后面的参数怎么回事?app
经过apply和call实现数组追加:函数
var arr1 = [1,2,3,4];
Array.prototype.push.apply(arr1, [5,6,7]); //调用数组原型上的push方法,至关因而arr1借用了push方法实现尾部追加元素,第二个元素是以数组形式
console.log(arr1) //[1, 2, 3, 4, 5, 6, 7]复制代码
var arr1 = [1,2,3,4];
Array.prototype.push.call(arr1,5,6,7); //而call方法是已参数列表形式传入追加的元素
console.log(arr1) //[1, 2, 3, 4, 5, 6, 7]复制代码
function createPerson(name,age,job) {
var obj = new Object(); //建立一个对象
obj.name = name; //给对象添加属性 和方法
obj.age = age;
obj.job = job;
obj.sayName = function() {
console.log(this.name)
}
return obj; //返回这个对象
}
var person1 = createPerson("lili", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
console.log(person1 instanceof createPerson) //false
console.log(person2 instanceof createPerson) //false复制代码
优势:解决了建立多个对象的时候的重复代码问题。ui
缺点:不能解决对象识别问题,也就是不知道一个对象的类型,上面的instanceof 说明问题。this
ECMAScript中的构造函数可用来建立特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出如今运行环境中,咱们能够建立自定义的构造函数,从而定义自定义对象类型的属性和方法。下面就是使用构造函数模式将前面的例子重写以下:spa
function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
console.log(this.name);
}
}
var person1 = new Person("lili", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
console.log(person1 instanceof Person); // true 这里能够判断其属于Person类型的实例对象了
console.log(person2 instanceof Person); // true复制代码
咱们能够注意到,Person()中的代码除了与createPerson()中相同的部分外,还存在如下不一样之处:prototype
注意: 经过new实例化的对象,咱们就能够明确知道了其类型,code
要建立Person的新实例,必须使用new操做符,那么new的过程当中都经历了那几个步骤呢:对象
咱们尝试本身用代码来实现一下new过程吧!!!
function New(Person,name,age,job) { //Person是上面那个构造函数
//1.建立一个对象,
var obj = {};
//2.将构造函数的做用域赋给新对象,所以this就指向了这个新对象,这里咱们将obj的__proto__指向了Person的prototype,由于通用new出来的实例的__proto__属性都指向构造函数的原型(prototype)
obj.__proto__ = Person.prototype;
//执行构造函数Person中的代码,这里经过apply将做用域切换为当前obj,这里的arguments是New方法传入的参数,经过slice去掉第一个参数,传入剩下的参数,
var ret = Person.apply(obj,Array.prototype.slice.call(arguments,1));
// 若是ret是对象或者是函数,就返回,若是不是就返回obj;
if((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
return ret;
}
return obj;
}
var o = New(Person,'jiji',1,'mother');
console.log(o)复制代码
码字不易,若是对你有帮助的话,不忙点个赞再走~~~~~