面试必问之原型链与继承以及call/bind/apply

【面试必问之原型链与继承以及call/bind/apply】一卷旌收千骑虏,万全身出百重围。这篇文章主要讲述面试必问之原型链与继承以及call/bind/apply相关的知识,希望能为你提供帮助。

/**1、对象
*创建对象:
var obj = new Object();
var obj = {};
对象的继承与原型链:
每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __proto__ ) ,
层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

* **/
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
f.prototype.b = 3;
f.prototype.c = 4;
console.log(o.a) // 1
console.log(o.b)
// b是o的自身属性吗?是的,该属性的值为 2
// 原型上也有一个‘b‘属性,但是它不会被访问到。
// 这种情况被称为"属性遮蔽 (property shadowing)"
console.log(o.c) // 4

/**2、继承
*当继承的函数被调用时,this 指向的是当前继承的对象,而不是继承的函数所在的原型对象。
* **/
var o = {
a: 2,
m: function(){
return this.a + 1;
}
};
console.log(o.m()); // 3
// 当调用 o.m 时,‘this‘ 指向了 o.
var p = Object.create(o);
// p是一个继承自 o 的对象
p.a = 4; // 创建 p 的自身属性 ‘a‘
console.log(p.m()); // 5
// 调用 p.m 时,‘this‘ 指向了 p
// 又因为 p 继承了 o 的 m 函数
// 所以,此时的 ‘this.a‘ 即 p.a,就是 p 的自身属性 ‘a‘

/**
3、不同方法来创建对象和生成原型链;
**/

// 字面量法
var bj = {a: 1}; //原型链为: bj --> Object.prototype --> null

//数组
var arr = [‘1‘,‘2‘];
//数组都继承于Array.prototype(Array.prototype中包含indexf,forEach等方法)
// 原型链如下: arr --> Array.prototype --> Object.prototype --> null

//函数
function f(){
return 2;
}
//函数都继承于 Function.prototype (Function.prototype中包含call,bind等方法)
//原型链如下: f ---> Function.prototype ---> Object.prototype ---> null

//构造函数
function Graph() {
this.vertices = [];
this.edges = [];
}

Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};

var g = new Graph();
// g 是生成的对象,他的自身属性有 ‘vertices‘ 和 ‘edges‘。
// 在 g 被实例化时,g.[[Prototype]] 指向了 Graph.prototype。

//Object.create创建的对象
var a = {a: 1};
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype

//使用class关键字创建的对象
//新的关键字包括 class, constructor,static,extends 和 super。
class Father {
constructor(name,age){
this.name = name;
this.age = age;
}
}

class Son extends Father{
constructor(change){
super(change,change)
}
get area(){
return this.name + this.age;
}
set change(newObj){
this.name = newObj;
this.age = newObj;
}
}

var s = new Son(‘mixue‘);

console.log(s);
// Son {name: "mixue", age: "mixue"}
// area: "mixuemixue"
// name: "mixue"
// age: "mixue"

/**
4、call、bind和apply
call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

call和apply、bind
call() //第二个参数为对象
apply() //第二个参数为数组
bind()
这三种作用:
相似点:
1、 改变this指向;
2、第一个参数都是this要指向的对象;
3、都可以利用后续参数传参;
不同点:写法不同
1、obj.call(xh,” c1” ,” c2” );        
2、obj.bind(xh,” c1” ,” c2” )();
3、obj.apply(xh,[“ c1” ,” c2” ]);
4、由于bind返回的仍然是一个函数,所以我们还可以在调用的时候再进行传参。
obj.bind(xh)(“ c1” ,” c2” );

call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以;

可以用来求数组最大值或最小值: Math.max/min.apply(null,[1,2,3,4]);
**/


    推荐阅读