1,构造函数内部原理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
前提必须要加 new,以下三步都是隐式的:
1.在函数体最前面隐式的加上 var this = {} 空对象
2.执行 this.xxx = xxx;
3.隐式的返回 return this
模拟写以下 new
Person.prototype.name = 'mike';
function Person (age) {
this.age = age;
}
var person = new(Person)(18);
console.log(person.age);
console.log(person.name);
var newNew = function (fn) {
var self = Object.create(fn.prototype);
var fun = function () {
var args = arguments;
fn.apply(self,args);
return self;
}
return fun;
}
var persona= newNew(Person)(18);
console.log(persona.age);
console.log(persona.name);
看似我们模拟的这个new是成功的.
也有助于理解我们日后使用new以及this指向问题.
但按照我模拟写的newNew 无论我在Person(){}里return 什么东西,
最终return 的都应该是 self
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Person.prototype.name = 'mike';
function Person (age) {
this.age = age;
var fun = function () {console.log(12346);};
return 5 当return 5的时候确实没有任何作用
return fun 当return一个引用值的时候,就会取代self
而用我自己写的newNew的时候,则即使是引用值也不会产生作用.
这表明:我模拟的new还是跟原生new是不一样的.
其次,我不明白这样设置有什么用意.
因为返回的东西似乎也并不能继承原型链.
}
var person = new(Person)(18);
console.log(person.age);
console.log(person.name);
var newNew = function (fn) {
var self = Object.create(fn.prototype);
var fun = function () {
var args = arguments;
fn.apply(self,args);
return self;
}
return fun;
}
var persona= newNew(Person)(18);
console.log(persona.age);
console.log(persona.name);
网上有涉及相同内容的: https://blog.csdn.net/SpicyBoiledFish/article/details/70858565
我看了这篇文章,然我脑子又变得复杂了 你不知道的javascript之Object.create 和new区别 https://blog.csdn.net/blueblueskyhua/article/details/73135938
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
刚开始,我看到博主写一个
Base.protytpe.name = 'mike'
function Base () {}
var obj = Object.create(Base);
这种语句,我就感觉这人是不是有毛病, 因为我的常识告诉我,不能放函数,应该放对象.
应该
var obj = Object.create(Base.prototype);
后来我细思量,觉得前一种也能间接继承,
obj.prototype.name // 返回mike
这是因为Base这个函数是一种特殊的对象,prototype应该是Base的一个属性.
obj继承了Base, 那么obj就应该能访问Base上的任何属性,以及Function.prototype上的任何属性
所以obj.继承Base,也能间接调用Base.prototype上的属性和方法.
当然,this默认不指向obj.
其实感觉也没什么用处.
不过一个对象的原型,可以是一个函数,一个函数可以成为另一个对象的原型,
这个事实本身还是很开脑洞的.
第二个让我脑子复杂的是模拟Object.create()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在上面,我是用Object.create()来模拟的new
而在这篇博客里面,有写到用 new模拟Object.create.
Object.create = function (obj) {
function F () {};
F.prototype = obj;
return new F();
}
咦? 这样确实有助于我们了解 create, 但变成是鸡生蛋还是蛋生鸡的问题了.
我们总不能 用new 和 create相互模拟吧?
而实际上 new可以不用 create模拟
var newNew = function (fn) {
var obj = {};
obj.__proto__ = F.prototype;
function F () {
fn.apply(obj,arguments);
return obj;
}
return F;
}
这虽然看起来没用new 实际上 {} 是 new Object() 来的吧?
紧接着后面又出现一个让我稍微混乱的东西 博主 分析 instanceof 和 isPrototypeOf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
让我混乱的就是: 博主用 instanceof 模拟 isPrototypeOf
function isRelatedTo(o1,o2){
function F(){}
F.prototype = o2;
return o1 instanceof F;
}
这我一看,第一眼我是觉得这个不靠谱的啊!
因为o1的原型链上不可能有F 的啊!!这F是这个isRelatedTo执行的时候才定义的好嘛?!
测试结果让我混乱了,确实跟isPrototypeOf的效果是一样的.
后来经过另外一些简单测试,得出一个结论,
这个instanceof F中的F的原型只要在某个实例对象的原型链上,
那么这个 instanceof 就都会返回true.......
比如说
function Person0 () {this.name = 0}
var person = new Person0();
function Person1() {this.name = 1}
function Person2() {this.name = 2}
function Person3() {this.name = 3}
Person1.prototype = Person2.prototype = Person3.prototype = Person0.prototype;
请问
person instanceof Person1 /2/3 返回什么? 返回true!
如果直接
Person0.prototype = Person1.prototype
person instanceof Person0 返回什么? 返回false..
最后的结论是, instanceof 是靠不住的, 可能 isPropertyOf 靠得住吧.
大家应该还记得 constructor 是靠不住的吧, 现在instanceof 也阵亡了.
============================= 虽然上面写得逻辑不是很清楚, 但足以表明我当时学的还是挺认真的, 挺有专研精神的
好了,我们补一下, 之前的模拟new 是有个缺陷的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function myNew (fun) {
return function () {
var self = Object.create(fun.prototype);
fun.apply(self,arguments)
return self;
}
}
这样 虽然能够返回 this
也能正常继承.
但如果构造函数内部返回一个引用值时,就无法模拟了
所以可以这样
function myNew (fun) {
return function () {
var self = Object.create(fun.prototype);
var result = fun.apply(self,arguments)
if (typeof result == "object") {// 判断返回值的类型
return result
}
return self;
}
}