一、继承
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__); // Objectarguments.__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.prototypeconsole.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 = fn1obj.$fn = this; // fn2.$fn = fn1obj.$fn(...ary); // fn2.$fn()相当于函数fn1(); ==> 1}// fn1.call.call(fn2); // call(); 相当于fn2.$fn();中this指向fn2function call (obj,...ary) { // obj = fn2 this = fn1.call obj = window this = fn2obj.$fn = this; // fn2.$fn = call() window.$fn2 = fn2obj.$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.prototypeobj.$fn = this; // fn1.$fn = Function.prototypeobj.$fn(...ary); // fn1.$fn()相当于函数Function.prototype();// Function.prototype是一个空函数 ==>没有结果}// Function.prototype.call.call(fn1); // call();相当于fn1.$fn();其中的this指向fn1function call (obj,...ary) { // obj = fn1 this = Function.prototype.call obj = window this = fn1obj.$fn = this; // fn1.$fn = Function.prototype.call window.$fn = fn1obj.$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添加了属性$fnres = 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);
