面向对象和NEW

164 阅读3分钟

1. OOP

  1. OOP(Object Oriented Programming):面向对象程序设计
  2. POP(Procedure Oriented):面向过程程序设计

2. 类

实例
1Number
'A'String
trueBoolean
nullNull->Object
undefinedUndefined
[]Array
/^$/RegExp
function(){}Function
{}Object

每一个元素标签(元素对象)都有一个自己所属的大类

  1. div -> HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget -> Object
  2. 每一个实例可以调用所属类(整条链)中的属性和方法(原型链)

创建一个自定义类

  • 创建一个函数(Function类的实例),直接执行就是普通函数,但是new 执行它则被称为一个自定义的类

NEW 函数执行

  • 形成一个全新的执行上下文EC
  • 形成一个AO变量对象
    • ARGUMENTS
    • 形参赋值
  • 初始化作用域链
  • 默认创建一个对象,而这个对象就是当前类的实例(比普通函数执行多的点)
  • 声明其THIS指向,让其指向这个新创建的实例(比普通函数执行多的点)
  • 代码执行
  • 不论其是否写RETURN,都会把新创建的实例返回(特殊点)(比普通函数执行多的点)
// 普通函数执行
func(); //=>this:window  AO(FUNC):{x=100} 

        // 当做new执行
function func() {
                // let obj={}; //=>这个对象就是实例对象
                // this 指向 obj
                let x = 100;
                this.num = x + 100; //=>相当于给创建的实例对象新增一个num的属性 
                // obj.num=200 (因为具备普通函数执行的一面,所以只有this.xxx=xxx才和创建的实例有关系,此案例中的x只是AO中的私有变量)
                // return obj;  用户自己返回内容,如果返回的是一个引用类型值,则会把默认返回的实例给覆盖掉(此时返回的值就不在是类的实例了)
        }
        
let f = new func();
console.log(f); //=>f是func这个类的实例 {num:200}

let f2 = new func();
console.log(f === f2); //=>false 每一次new出来的都是一个新的实例对象(一个新的堆内存)

//instanceof用来检测某一个实例是否属于这个类
console.log(f instanceof func); //=>TRUE 


手写: 自己实现一个new

  1. 默认创建一个实例对象(而且是属于当前这个类的一个实例)
  2. 也会把类当做普通函数执行
  3. 执行的时候要保证函数中的this指向创建的实例
  4. 若客户自己返回引用值,则以自己返回的为主,否则返回创建的实例
function Dog(name) {
	this.name = name;
}
Dog.prototype.bark = function () {
	console.log('wangwang');
};
Dog.prototype.sayName = function () {
	console.log('my name is ' + this.name);
};

/* 
 * 内置NEW的实现原理 
 * @params
 *    Func:操作的那个类
 *    ARGS:NEW类的时候传递的实参集合
 * @return
 *    实例或者自己返回的对象
 */
function _new(Func, ...args) { 
    // write your code here
    
	//1. 默认创建一个实例对象(而且是属于当前这个类的一个实例)
	// let obj = {}; // 这样不行,这样只创建了对象,原型没有指向Func.prototype
	// 应该改变obj原型链: obj.__proto__ = Func.prototype; //=> 但是, IE大部分浏览器中不允许我们直接操作__proto__
	let obj = Object.create(Func.prototype); //创建一个空对象,让这个空对象的.__proto__, 指向新地址。也就是,创建一个继承自Func.prototype的新对象

	//2. 也会把类当做普通函数执行
	//3. 执行的时候要保证函数中的this指向创建的实例
	let result = Func.call(obj, ...args);

	//4. 若客户自己返回引用类型,则以自己返回的为主,否则返回创建的实例
	//  typeof obj == 'obj'   typeof array == 'obj'  typeof function == "function"
	//  因为 typeof null =="obj", 所以需要把把null排除
	if ((result !== null && typeof result === "object") || (typeof result === "function")) {
		return result;
	}
	return obj;
}
let sanmao = _new(Dog, '三毛');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 三毛"
console.log(sanmao instanceof Dog); //=>true
  • let obj = Object.create(Func.prototype):
    • 会将参数对象作为一个新创建的空对象的原型(让这个空对象的.__proto__, 指向新地址。), 并返回这个空对象

    • 也就是,创建一个继承自Func.prototype的新对象。

  • typeof:
  • 实现Object.create()
//简略版
function myCreate(obj){
    // 新声明一个函数
    function C(){};
    // 将函数的原型指向obj
    C.prototype = obj;
    // 返回这个函数的实力化对象
    return new C()
}