Mình xét một ví dụ như sau:
// use this
function exFunction() {
    this.a = function() {
        console.log("Hello")
    }
}
Khi bạn muốn tạo function theo approach này thì bạn phải thận trọng với this. Vì this sẽ được sử dụng với context của object gọi nó. Ví dụ khi bạn gọi hàm exFunction thì kết quả sẽ là như thế nào?
function exFunction() {
    this.a = function() {
        console.log("Hello")
    }
}
exFunction()
console.log(window.a) 
/*
 * f() {
 *     console.log("Hello")
 * }
 */
Bạn đã vô tình thêm 1 property vào object window hoặc global. Còn khi bạn dùng prototype thì sẽ không bị như vậy.
Một lưu ý nữa là khi bạn dùng this. thì các instance của exFunction sẽ sử dụng phương thức riêng của nó.
function exFunction() {
    this.greet = function() {
        console.log("Hello")
    }
}
exFunction.prototype.changeGreeting = function(value) {
    this.greet = function() {
        console.log(value)
    }
}
let a = new exFunction()
let b = new exFunction()
a.greet() // Hello
b.greet() // Hello
a.changeGreeting("Xin chao")
a.greet() // Xin chao
b.greet() // Hello
Bạn có thể thấy các instance sử dụng function của nó độc lập với nhau. Còn khi sử dụng prototype:
function exFunction() {}
exFunction.prototype.greet = function() {
    console.log("Hello")
}
exFunction.prototype.changeGreeting = function(value) {
    exFunction.prototype.greet = function() {
        console.log(value)
    }
}
let a = new exFunction()
let b = new exFunction()
a.greet() // Hello
b.greet() // Hello
a.changeGreeting("Xin chao")
a.greet() // Xin chao
b.greet() // Xin chao
Khi dùng prototype thì các instance sẽ dùng chung share property qua [[Prototype]]