js-new

How to understand javascript new operation?

A easy example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function soldier(ID) {
var temp_obj = {};// ① new helps us a temp_obj
temp_obj.__proto__ = soldier.prototype;//② new helps us bind the prototype
temp_obj.ID = ID;
temp_obj.life = 42;

return temp_obj;//③ new helps us return the temp_obj;
}

soldier.prototype = {//④ new helps us define "prototype"
type: "Jiefangjun",
attack: 5,
walk: function(){},
run: function(){},
attack: function(){},
defend: function(){},
die: function(){},
}

Using new, we can prevent doing the following things:

  • Creating a temporary object (directly using this to visit the temporary object)
  • Binding prototype (new knows where your prototype is)
  • Returning temporary object
  • Giving a name to “prototype”

After we using new :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function soldier(ID) {
this.ID = ID;
this.life = 42;
}

soldier.prototype = {
type: "Jiefangjun",
attack: 5,
walk: function(){},
run: function(){},
attack: function(){},
defend: function(){},
die: function(){},
}

var soldiers = []
for(let i=0; i<100; ++i) {
soldiers.push(new soldier(i))
}

There is a property named constructor:

1
2
3
soldier.prototype = {
constructor: soldier
}

So we need to define the property seperatedly.

Implement a new by self

First let’s do a test:

1
2
3
4
5
6
7
8
9
function Test(name) {
this.name = name
}
Test.prototype.sayName = function () {
console.log(this.name)
}
const t = new Test('cxk')
console.log(t.name) // 'cxk'
t.sayName() // 'cxk'

Test if we return a value in the function:

1
2
3
4
5
6
function Test(name) {
this.name = name
return 1
}
const t = new Test('cxk')
console.log(t.name) // 'cxk'

So if we return a value in the function, there is no difference.

Test if we return an object in the function:

1
2
3
4
5
6
7
8
function Test(name) {
this.name = name
console.log(this) // Test { name: 'yck' }
return { age: 26 }
}
const t = new Test('yck')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'

So if we return an object, the new doesnt effect.

1
2
3
4
5
6
function create(fun, ...args) {
let obj = {};//create a temp_obj
Object.setPrototypeOf(obj, fun.prototype)//bind the temp_obj to prototype
let result = fun.apply(obj, args)//bind obj to construction function
return result instanceof Object ? result: obj;
}

Then we test function create :

1
2
3
4
5
6
7
8
9
10
11
function Test(name, age) {
this.name = name
this.age = age
}
Test.prototype.sayName = function () {
console.log(this.name)
}
const a = create(Test, 'cxk', 21)
console.log(a.name) // 'cxk'
console.log(a.age) // 21
a.sayName() // 'cxk'