new 运算符建立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例数组
其实咱们了解了new的整个过程咱们是比较容易去实现一个new的 1.let obj = {} 或者 let obj = new object(); 二者等价 2.obj.proto = Func.prototype (Func为构造函数) 3.经过apply改变this,以访问函数内部变量 4.返回bash
function New() {
let obj = {}; // 建立对象
console.log(arguments);
let constructor = [].shift.call(arguments); // 获取构造函数
console.log(arguments);
if (constructor.prototype !== null) {
obj.__proto__ = constructor.prototype; // 构造函数连接到新对象
}
let ret = constructor.apply(obj, [].slice.call(arguments)); // 改变this指向
console.log(arguments);
console.log(typeof ret);
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return obj; // 若是函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用将返回该对象引用。
}
function name(a, b) {
this.a = a;
this.b = b;
}
let c = New(name, 1, 2)
let d = new name(1, 2)
console.log(c);
console.log(d);
复制代码
咱们来看返回值:app
咱们看到New 和 new产生了一样的效果函数
注意:[].shift.slice()会改变咱们的arguments。typeof null == "object"性能
重点:为何要进行对象判断,通常实现new时会把这一点的解释给忽略。优化
默认状况下函数的返回值为undefined(即没有显示地定义返回值的话),可是构造函数比较例外,new构造函数在没有return的状况下默认返回新建立的对象。可是在有显示返回值的状况下,若是返回值为基本数据类型的话(string,number,boolean,undefined,null),返回值仍然为新建立的对象,这一点比较奇怪,须要注意。只有在显示返回一个非基本数据类型的对象的时候,函数的返回值才为指定的对象。在这种状况下,this值所引用的对象就被丢弃了。ui
看下面两个例子:this
例1: spa
例2: prototype
// return; // 返回 this
// return null; // 返回 this
// return this;
// return []; // 返回 []
// return function(){}; // 返回 这个 function,抛弃 this
// return false; // 返回 this
// return new Boolean( false); // 返回新 boolean;抛弃 this
// return 'hello world'; // 返回 this
// return new String( 'hello world'); // 返回 新建的 string,抛弃 this
// return 2; // 返回 this
// return new Number( 32); // 返回新的 number,抛弃 this
arguments 是一个对应于传递给函数的参数的类数组对象。
arguments 对象只能在函数内使用
将arguments转换成数组
相似的转换方法
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);
// ES2015
const args = Array.from(arguments);
const args = [...arguments];
MDN上不建议咱们对参数进行slice 解决方案:
function New() {
let obj = {}; // 建立对象
console.log(arguments);
let constructor = [].shift.call(arguments); // 获取构造函数
console.log(arguments);
if (constructor.prototype !== null) {
obj.__proto__ = constructor.prototype;
}
let ret = constructor.apply(obj, (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)));
console.log(ret);
console.log(arguments);
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return obj;
}
function name(a, b) {
this.a = a;
this.b = b;
}
let c = New(name, 1, 2)
let d = new name(1, 2)
console.log(c);
console.log(d);
复制代码
对参数使用slice会阻止某些JavaScript引擎中的优化。若是你关心性能,尝试经过遍历arguments对象来构造一个新的数组。另外一种方法是使用被忽视的Array构造函数做为一个函数
获取arguments的第一个参数,改变arguments的length
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
.slice()方法
定义和用法 slice(start, end) 方法可提取数组的某个部分,并以新的数组返回被提取的部分。
使用start(包含) 和 end(不包含)
参数来指定提取数组开始和结束的部分。
若是未指定start和end,则返回整个数组。
若是指指定一个参数,该参数做为start使用,返回包括start位置以后的所有数组。
若是是负数,则该参数规定的是从数组的尾部开始算起的位置。也就是说,-1 指数组的最后一项,-2 指倒数第二个项,以此类推。
改变[]中的this指向
改变this的指向
经过 apply指向 apply将构造函数的this指向新建立的对象
array.form() 或者 ... 或则遍历
类数组对象的key值为数字
Array.prototype.slice = function(start,end){
var result = new Array();
start = start || 0;
end = end || this.length; //this指向调用的对象,当用了call后,可以改变this的指向,也就是指向传进来的对象,这是关键
for(var i = start; i < end; i++){
result.push(this[i]);
}
return result;
复制代码