一、继承
1、原型继承
// 1、原型继承
// 需求:有A类、B类,想要让B所有的实例继承A类私有的和公有的属性和方法
// 利用原型继承:让B类的原型指向A类的实例(因为A类的实例上边,既有A类的私有属性和方法,也可以通过__proto__找到A类原型上的属性和方法)
// IE中不允许这么更改原型
function A () {
this.a = "a";
};
A.prototype.getA = function () {
console.log("A类的公有方法getA()")
};
function B () {
this.b = "b";
};
B.prototype = new A();
var b1 = new B();
console.log(b1);
console.log(b1.a);
console.log(b1.getA);
2、中间类继承
// 2、中间类继承
// 需求:,某些实例并不属于某类,但是想用该类原型上的方法;
// 我们可以手动更改实例的__proto__,让他指向该类的原型
function fn() {
// console.dir(arguments.sort); // undefined 由于arguments类数组对象中没有sort属性
console.dir(arguments.__proto__); // Object
arguments.__proto__ = Array.prototype;
var res = arguments.sort(function (a,b) {
return a-b;
})
return res;
}
var r = fn(9, 7, 5, 3, 1);
console.log(r);
3、call继承
// call()方法,用来改变this指向
// call继承
// 需求:A类和B类,想要让B类的实例用有A类的私有属性
// 可以让A当成普通函数执行,把里面的this指向改为B类的实例(让A类給B类的实例中添加属性)
function A() {
this.a = "a";
this.x = 100;
};
function B() {
A.call(this);
this.b = "b";
this.y = 200;
}
var b = new B();
console.log(b);
4、寄生结合继承
// 寄生组合继承
// A类、B类,B类想要继承A类的私有和公有
// call()方法继承私有属性; 利用一个空对象接受某个原型身上的属性,再这个对象赋值给需要继承的原型上
function A() {
this.a = "a";
this.x = 100;
}
A.prototype.getA = function () {
console.log("A");
}
function B() {
A.call(this);
this.b = "b";
this.y = 300;
}
/* var obj = {};
obj.__proto__ = A.prototype;
B.prototype = obj; */
// Object.create();
B.prototype = Object.create(A.prototype); // 创建一个新对象,并将其值设置为B.prototype;
// 该新对象的__proto__指向A.prototype
console.log(B.prototype.prototype);
var b = new B();
console.log(b);
console.log(b.getA());
二、改变this指向的方法 :call、apply、bind
this指向不可以手动更改
// this指向不可以手动更该
var name = "window";
function fn() {
this = 100;
console.log(this); // 报错
}
fn();
1、call
// call(); 方法更改this指向
var name = "window";
function fn(x, y) {
console.log(this.name);
return x + y;
};
var obj = {
name: "objName",
age: "18"
};
// 第一个参数:更改的this指向
// 第二个参数:
//
fn.call(obj, 1, 3);
/* 执行过程
1、通过原型链找到Function.prototype 上的call();方法
2、找到之后,让fn 执行call();
3、执行时,需要把函数内部的this指向改变为call()的第一个参数
*/
// call(); 传递第一个参数的特殊情况
// 非严格模式下:不传参、null、undefined this都指向window
// 严格模式下:不传参 this指向undefined;undefined this指向undefined;null this指向null。
111 关于call();方法的坑题
关于Function.prototype
这是一个空函数 Function.prototype();没有执行结果 返回值为undefined
Function.prototype是一个空函数
ƒ () { [native code] } // 返回值
Function.prototype();
undefined // 函数执行的返回值
function fn1(){
console.log(1);
}
function fn2(){
console.log(2);
}
fn1.call(fn2);
fn1.call.call(fn2);
Function.prototype.call(fn1);
Function.prototype.call.call(fn1);
答案
// fn1.call(fn2);
function call (obj,...ary) { // obj = fn2 this = fn1
obj.$fn = this; // fn2.$fn = fn1
obj.$fn(...ary); // fn2.$fn()相当于函数fn1(); ==> 1
}
// fn1.call.call(fn2); // call(); 相当于fn2.$fn();中this指向fn2
function call (obj,...ary) { // obj = fn2 this = fn1.call obj = window this = fn2
obj.$fn = this; // fn2.$fn = call() window.$fn2 = fn2
obj.$fn(...ary); // fn2.$fn()相当于函数call(); window.$fn2();相当于函数fn2()执行 ==>2
}
// Function.prototype是一个空函数
// ƒ () { [native code] } // 返回值
// Function.prototype();
// undefined // 函数执行的返回值
// Function.prototype.call(fn1);
function call (obj,...ary) { // obj = fn1 this = Function.prototype
obj.$fn = this; // fn1.$fn = Function.prototype
obj.$fn(...ary); // fn1.$fn()相当于函数Function.prototype();
// Function.prototype是一个空函数 ==>没有结果
}
// Function.prototype.call.call(fn1); // call();相当于fn1.$fn();其中的this指向fn1
function call (obj,...ary) { // obj = fn1 this = Function.prototype.call obj = window this = fn1
obj.$fn = this; // fn1.$fn = Function.prototype.call window.$fn = fn1
obj.$fn(...ary); // fn1.$fn()相当于函数call window.$fn1();相当于函数fn1()执行
2、apply
// apply();
var name = "window";
function fn(x, y) {
console.log(this.name);
return x + y;
};
var obj = {
name: "objName",
age: "18"
};
// 第一个参数:更改的this指向
// 第二个参数:以数组(类数组)形式进行传参
// apply(); 和call(); 传形式不同
fn.apply(obj, [1, 3]);
3、bind
// bind(); 预处理this指向,
// 只是预先处理了this指向,并不能让函数执行,
// 想要让函数执行:就再 调用一次返回值;或者给函数绑定一个触发事件
// bind(); 返回值为更改this指向后的函数
var name = "window";
function fn(x, y) {
console.log(this.name);
return x + y;
};
var obj = {
name: "objName",
age: "18"
};
// 第一个参数:更改的this指向
// 第二个参数:
//
fn.bind(obj, 1, 3);
fn.bind(obj, 1, 3)(); // 改边this指向后的函数fn执行;
4、封装call(); 方法
Function.prototype. Mycall = function (obj, ...arg) {
obj = obj || window;
var res;
obj.$fn = this; // 函数fn赋值給obj.$fn; 并且給obj添加了属性$fn
res = obj.$fn(...arg); // obj.$fn();执行的时候this指向obj(达到了改变this指向的目的)
delete obj.$fn; //
return res; // 把函数obj.$fn()的返回值暴漏出去;(也就是fn()执行的返回值)
}
var obj = {name : "objname", age:18};
function fn(x, y) {
console.log(this.name);
return x+y;
}
// fn(3, 4);
fn. Mycall(obj, 1, 2);
var obj2 = {
name : "123",
age : 19
};
fn. Mycall(obj2, 3, 2);