咏竹莉
where there is a will,there is a way
// 原型对象
var Student = {
    name: 'Robot',
    height: 1.2,
    run: function(){
        console.log(this.name + ' is running')
    }
};
function createStudent(name){
    // 基于Student原型创建一个新对象
    var s = Object.create(Student);
    // 初始化新对象
    s.name = name;
    return s;
}
var xiaoming = createStudent('xiaozhu');
xiaoming.run();                 // xiaozhu is running
console.log(xiaoming.height);   // 1.2
console.log(xiaoming.__proto__ === Student);   // true

  

创建对象

javascript对每个创建的对象都会设置一个原型,指向它的原型对象。

当我们用 obj.xxx 访问一个对象的属性时,js引擎先再当前对象上查找该属性,如果没找到,就到其原型对象上查找,如果还没有找到,就一直上溯到Object.prototype 对象, 然后,如果还没有找到,就只能返回undefined。

例如:创建一个Array对象:

var arr = [1,2,3]

 其原型链是:

arr ---> Array.prototype  ---> Object.prototype ---> null

 

Array.prototype 定义了indexOf()shift() 等方法,因此可以在所有的Array对象上直接调用这些方法。

当我们创建一个函数时:

function foo() {
  return 0;  
}

函数也是一个对象,它的原型链是

foo ---> Function.prototype ---> Object.prototype ---> null

Function.prototype 定义了 apply() 等方法,因此,所有函数都可以调用apply() 方法。

 

构造函数

除了直接用{...}  创建一个对象外,js还可以使用一种构造函数的方法来创建对象。 先定义一个构造函数:

function Student(name){
    this.name = name;
    this.hello = function(){
       console.log('Hello ' + this.name + '!')
    }    
}

 

在js中,可以用关键字 new 来调用这个函数,并返回一个对象:

var xiaoming = new Student('小明');
xiaoming.name;        // 小明
xiaoming.hello();     // Hello, 小明!

注意: 如果不写 new ,这就是一个普通函数,它返回undefined, 但是。如果写了new ,它就变成了一个构造函数,它绑定的this 指向了新创建的对象,并默认返回this。 也就是说,不需要在最后写 return this

新创建的xiaoming的原型链是:

xiaoming--->  Student.prototype ---> Object.ptototype ---> null

再创建xiaohong、xiaojun,那么这些对象的原型与xiaoming是一样的:

xiaoming ↘
xiaohong -→ Student.prototype ----> Object.prototype ----> null
xiaojun  ↗

不过有个小问题:

xiaoming.name;   // '小明'
xiaohong.name;   // '小红'
xiaoming.hello;    // function: Student.hello()
xiaohong.hello;    // function: Student.hello()
xiaoming.hello === xiaohong.hello;   // false

xiaoming 和 xiaohong各自的name不同,这是对的,否则我们取法区分谁是谁了。

xiaoming和xiaohong各自的hello是一个函数,但它们是两个不同的函数,虽然函数名称和代码都是相同的!

如果我们通过new Student() 创建了很多对象,这些对象的hello 函数实际上只需要共享同一个函数就可以了,这样可以节省很多内存。

修改代码如下:

function Student(name) {
    this.name = name;  
}
// 公共方法 Student.prototype.hello
= function (){ console.log(`Hello ${this.name}`) }

 

为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写。

我们还可以编写一个createSdtudent() 函数。在内部封装所有的new操作。一个常用的编程模式:

      function Student(props) {
            this.name = props.name || '匿名';   // 默认值为’匿名‘
            this.age = props.age || 18;      // 默认值为18
        }
        Student.prototype.hello = function(){
            console.log(`Hello ${this.name}`)
        }
        function createStudent(props){
            return new Student(props || {})
        }

        var xiaozhu = createStudent({
            name: 'xiaozhu'
        })
        console.log(xiaozhu.age);    // 18
        xiaozhu.hello();             // Hello xiaozhu

        var xiaoli = createStudent({
            name: 'xiaoli',
            age: 20
        })

        console.log(xiaoli.name);   // xiaoli
        xiaoli.hello();             // Hello xiaoli

 

posted on 2021-06-29 14:42  咏竹莉  阅读(56)  评论(0)    收藏  举报