K0II / JavaScript

Learning Logs
0 stars 0 forks source link

new调用函数和普通调用函数的区别 #1

Open K0II opened 8 years ago

K0II commented 8 years ago

new调用函数和普通调用函数的区别(一)


function test() {
  this.name = 'Test';
  return function() { return true; }
}

var foo = new test();
var bar = test();

typeof foo;    //  function
typeof bar;    //  function

foo;    // function()
bar;    // function()

foo.name;    //  空字符串
bar.name;    //  空字符串

foo();    //  true
bar();    //  true

foo === bar;    //  false

var baz = test();
bar === baz;    //  false

各种测试发现,当test函数return的是一个函数的时候没有区别,哪怕foo === bar; // false 也不意外

K0II commented 8 years ago

new调用函数和普通调用函数的区别(二)


function test() {
  this.name = 'test';
  return 'test';
}

var foo = new test();
var bar = test();

typeof foo;    //  object
typeof bar;    //  string

foo;    // test { name="test"}
bar;    // test

foo.name;    //  test
bar.name;    //  undefined

foo();    //  TypeError: foo is not a function
bar();    //  TypeError: bar is not a function

再重新测试一遍发现,当test函数return的是一个字符串的时候,foo是一个对象test { name="test"},bar是test函数return的字符串,他俩都不是function

K0II commented 8 years ago

new调用函数和普通调用函数的区别(三)

function test() {
  this.name = 'test';
  return [1,2,3];
}

var foo = new test();
var bar = test();

typeof foo;    //  object
typeof bar;    //  object

foo;    // [1,2,3]
bar;    // [1,2,3]

foo.name;    //  undefined
bar.name;    //  undefined

foo();    //  TypeError: foo is not a function
bar();    //  TypeError: bar is not a function

没错,我又拿数组测了一遍,这回又没区别了,array和function都是对象子类型,属于js中六种主要类型中的object类型,所以我大胆猜测一下,除了返回js六种基本类型中的object类型以外的其他五种类型(string、number、boolean、undefined、null),使用new 函数调用将会返回一个该函数的实例对象。如果函数返回object类型的九种子类型也就是内置对象(Object、Array、Function、String、Number、Boolean、Date、RegExp、Error)的时候,则 new 函数与直接调用函数产生的结果等同。

当然,光猜测不行,我把所有的基本类型和内置对象都试了一遍,没必要再贴出来了,亲测有效,上面是对的。(除了null,这是js的bug)

之所以会出现这两种情况,是因为,在普通的函数调用前面加上new关键字以后,就会把这个函数调用变成一个构造函数调用,new会劫持所有普通函数,并用构造对象的形式来调用它。

也就是无论如何,new会构造一个对象并赋值给调用它的foo,typeof foo无论返回的是function还是object,都是对象。普通函数就比较老实,你返回什么我就是什么

K0II commented 8 years ago


在JavaScript中对于“构造函数”最准确的理解是:所有带new的函数调用。
函数不是构造函数,但是当且仅当使用new时,函数调用会变成“构造函数调用”

K0II commented 8 years ago

回顾一下原型

var Book = {
    num: 0,
    arr: [1,2,3],
    inc: function() {
        this.num ++;
        console.log(this.num);
    },
};

var b = Object.create(Book);
b.hasOwnProperty('num');  // false
b.inc();  // 1
b.inc();  // 2
b.inc();  // 3

Book.num;  // 0    没影响
b.hasOwnProperty('num');  //  true

b.arr.push(4);
b.arr;  //  [1, 2, 3, 4]
Book.arr;  //  [1, 2, 3, 4]    Holy shit