VueBloghyhero6

关于 JS 手动写一个new 的问题。

2019-09-18 / 2019-09-18 / 370次浏览

最近的事情好多,且最近的脾气有点小暴躁,有点生人勿进的意思,所有更新推迟延迟到了今天。(小声哔哔: 人倒霉喝凉水都是塞牙的,真的没有办法这个事情。)

首先了解 new 做了什么, 使用 new 关键字调用函数 (new ClassA( ... )) 的具体步骤

网上表明分了4步,
1、 创建一个新对象:
var obj = {};
2、 设置新对象的constructor 属性为构造函数的名称,设置新对象的_proto_属性指向构造函数的prototype对象;
obj.proto = ClassA.prototype;
3、 使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call( obj ); // {}.构造函数()
4、 将初始化完毕的新对象地址,保存到等号左边的变量中。
注意:若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。

简单的上下代码帮助理解
var a = function ( ) { return 1 }
new a // a { }
or new a( ) // a { }

下面的代码可以进行浏览器测试
var foo = "bar"
function test ( ) {
this.foo = "foo";
}

关于 this 调用 ,这里插一句,this 是谁调用指向谁,未调用指向全局,如果是严格模式下undefined

new test ( ) ; // test 中的this 指新对象,并未改变全局的foo 属性
console.log ( this.foo ); // "bar" 因为直接指向全局了
console.log ( new test ( ).foo ) // "foo" 这里调用了所以可以直接输出属性。

然后我们 对函数进行代码分析

// 通过分析原生的new方法可以看出,在new一个函数的时候,

// 会返回一个func 同时在这个func 里面会返回一个对象Object,

// 这个对象包含父类func的属性以及隐藏的_proto_

然后下面上代码

function New (f) {
// 返回一个对象
return function () {
var o = { "proto": f.prototype };
f.apply(o, arguments ) // 继承父类属性,arguments 表示 参数数组
return o; // 返回一个Object
}
}

这里暂停我做了一个实验,

function Person(name,age){
this.name = name;
this.age = age;
}

var p1 = new Person()
p1.color = 'red'
console.log(p1) // Person { age: undefind, color: "red", name: undefined }

看起来console.log(Person) // 返回如下直接返回一个对象没有毛病。

console.log(Person) // 返回如下
ƒ Person(name,age){

this.name = name;

this.age = age;

}
也就是你随意加属性 对原函数本身是没有影响的,想想也对,如果有影响那还乱了套了。

我们在试试这个

new Person().haha = 'haha' // haha 函数 执行然后释放

这个是 输出P1

console.log(p1) // Person {name: undefined, age: undefined, color: "red"}

想想这个也对,如果对P1 有影响依旧坏菜了,那就图样图森破了。

好了这个引用关系的实验 到此结束。

我们手动写了一个new 函数,(小声哔哔: 写个毛毛还是拿JS 实现)

咳咳,不在在意这些细节,反正真实项目谁也不会自己封装个new 玩的。 文章嘛重在理解。

上代码

function Person(name,age){
this.name = name;
this.age = age;
}
var p1 = new Person("Richard",22);
p1.name; // Richard
p1.age; // 22
var p2 = New( Person )("Jack", 25);
p2.name; // Jack
p2.age; // 25

看一眼他们的这个原型链

Person.prototype.gender = "male";
p1.gender // male
p2.gender // male

最后还有这个函数执行优先级的问题
从高到低: 小括号(xxx) > 属性访问. > new foo() >foo()

论调用时间戳的问题,一般傻子才会使用最后一种调用方式。

new Date().getTime();//===((new Date()).getTime)()
(new Date).getTime();//===((new Date()).getTime)()
new Date.getTime();//Uncaught TypeError: Date(...).getTime is not a function;===new (Date.getTime)()

最后看张小姐姐降降火吧-。-

JS基础,event