面试题——JS实例化过程总结(附原型链图解)

没有返回值的构造函数形式

function Person(name,age){
    this.name = name;
    this.age = age;
    this.show = function(){
        console.log('每个人的身上都有毛毛');
    }
}

var person = new Person('LiMing',22);
console.log(person);
person.show();//如果不调用,不会输出
console.log(person instanceof Person);
console.log(person.__proto__ == Person.prototype);

运行结果如下:

 

 如果实例没有调用方法,图中圈出的部分不能被输出;

 

 

 

根据图中显示结果,我们可以将实例化过程总结为:

1.创建了一个object对象{};
2.将构造函数的静态属性传递给创造的对象;
3.实例对象额外添加了__proto__属性,指向了构造函数的prototype属性,也就是原型对象;
4.构造函数的原型对象有一个constructor方法,返回值为构造函数;
5.构造函数内的this指向为实例对象;
另外:如果实例没有调用构造函数的方法,不会输出图中画框的部分;

 

 

 

如果有返回值的情况1:返回值为基本数据类型

function Person1(name,age){
    this.name = name;
    this.age = age;
    this.show = function(){
        console.log('每个人的身上都有毛毛');
    };
    return 22
}


var person1 = new Person1('LiMing',22);
console.log(person1);
person1.show();
console.log(person1 instanceof Person1);
console.log(person1.__proto__ == Person1.prototype);

 

 

 从结果看,基本的数据类型不影响实例过程;

如果有返回值的情况2:返回值为引用数据类型

function Person2(name,age){
    this.name = name;
    this.age = age;
    this.show = function(){
        console.log('每个人的身上都有毛毛');
    };
    return {
        name:"lihua",
        age:25,
        show:function () {
            console.log('你是我天边最美的云彩!')
        }
    }
}
var person2 = new Person2('LiMing',22);
console.log(person2);
person2.show();
console.log(person2 instanceof Person2);
console.log(person2.__proto__ == Person2.prototype);

 

function Person3(name,age){
    this.name = name;
    this.age = age;
    this.show = function(){
        console.log('每个人的身上都有毛毛');
    };
    return {
        weight:70,
        height:185,
        show:function () {
            console.log('你是我天边最美的云彩!')
        }
    }
}

var person3 = new Person3('LiMing',22);
console.log(person3);
person3.show();
console.log(person3 instanceof Person3);
console.log(person3.__proto__ == Person3.prototype);

 

function Person4(name,age){
    this.name = name;
    this.age = age;
    this.show = function(){
        console.log('每个人的身上都有毛毛');
    };
    return [12,23,'345',{name:'LiHua'}]
    
}


var person4 = new Person4('LiMing',22);
console.log(person4);
person4.show();
console.log(person4 instanceof Person4);
console.log(person4.__proto__ == Person4.prototype);

 从结果看,如果构造函数返回一个object的话,实例为返回的对象;

 

 

最后,附上一张本人觉得比较好的原型链图解

 

其中中间颜色加深部分,分为三种构造器,

1>自定义构造器;
2>对象构造器;
3>内置对象构造器(例如Array,String,Date,Match);

 

call、apply和bind区别

首先,call apply bind三个方法都可以用来改变函数的this指向,具体区别如下:

call( ) 是接收一个及其以上的参数,第一个参数表示this要指向的对象,其余参数表示调用函数需要传入的参数,返回调用函数的返回结果,属于立即执行函数;
apply( ) 是接收两个参数,第一个参数表示this要指向的对象,第二参数表示调用函数需要传入的参数所组成的数组,返回调用函数的返回结果,属于立即执行函数;
bind( ) 是接收一个及其以上的参数,和call()一致,但是其返回是一个函数,而不是调用函数的返回结果
call、apply、bind相同点:都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是nul或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组
bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
值得注意:当 bind 返回的函数 使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)

call的使用方法

const person = { 
 name: 'Alice', 
 sayHello: function () {  
        console.log(`Hello, ${this.name}!`)  
        },
}
const person2 = {  name: 'Bob',}
person.sayHello.call(person2) // 输出:Hello, Bob!

apply的使用方法

const person = { 
 name: 'Alice', 
 sayHello: function (greeting) {    
                 console.log(`${greeting}, ${this.name}!`) 
             },
}
const person2 = {  name: 'Bob',}
person.sayHello.apply(person2, ['Hi']) // 输出:Hi, Bob!
        

bind的使用方法

const person = {  
name: 'Alice',  
sayHello: function () {  
  console.log(`Hello, ${this.name}!`) 
 },
}
const person2 = {  name: 'Bob',}
const sayHelloToBob = person.sayHello.bind(person2)
sayHelloToBob() // 输出:Hello, Bob!
const person = { 
 name: 'Alice',  
sayHello: function (greeting, punctuation) {    console.log(`${greeting}, ${this.name}, ${punctuation}`) 
 },
}
const person2 = {  name: 'Bob',}
const sayHelloToBob = person.sayHello.bind(person2);
sayHelloToBob(1,2); // 输出:1, Bob, 2
this.x = 9;    // 在浏览器中,this 指向全局的 "window" 对象var module = { 
 x: 81, 
 getX: function() { 
return this.x; 
}
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();// 返回 9 - 因为函数是在全局作用域中调用的/
/ 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

 

posted on 2021-04-07 18:58  大毛猫熊  阅读(378)  评论(0编辑  收藏  举报