Object-oriented fundamentals

Constructors and normal functions perform differently

/* Normal function execution: + initialize scope chain + initialize this window/undefined + initialize arg + parameter assignment + variable promotion + code execution: @1 create the current instance object + initialize the scope chain + initialize this @2 this points to the created instance object + initialize arg + parameter assignment + variable promotion + code executes the value of return if it is a primitive value or returns the created instance object without writing a return If it's an object, it's an object */
function Fn(x, y) {
    let sum = 10;
    this.total = x + y;
    this.say = function () {console.log(' I calculated the sum is :${this.total}`);
    };
}
let res = Fn(10.20); // Normal function execution
let f1 = new Fn(10.20); // The constructor executes
let f2 = new Fn;
console.log(f1.sum);		//=>undefined
console.log(f1.total);		/ / = > 30
console.log(f1.say === f2.say); 	//=>false
Copy the code

Comb through the prototype chain

const fn = function fn(){}
let fn1 = new fn();
/* 1. Functions and objects have a __proto__,prototype attribute 2. 3. Object can --> function */
// Functions can --> objects
console.log(Function.__proto__.__proto__ === Object.prototype);	//=>true
// Objects can --> functions
console.log(Object.__proto__ === Function.prototype);	//=>true


/* · 1. The instance object has __proto__ but no prototype 2. Generally, @1 is not selected because it is incompatible with IE. IE does not have __proto__ */
/ / @ 1
console.log(fn1.__proto__ === fn.prototype);	//=>true
/ / @ 2
console.log(Object.getPrototypeOf(fn1) === fn.prototype); //=>true


Function instanceof Function //=>true 2. Function instanceof Object //=>true 3 Function instanceof Function //=>true function.__proto__ === function. prototype //=>true Prototype: call/applay/bind/call/ call/ bind Function instanceof Function //=>true console.log({}.__proto__ === object.prototype) //=>true __proto__ of any Object can be found in object. prototype only then can we guarantee that all functions can call object.hasownProperty () */
Copy the code

Tests whether a property is a “private property” of an object

Object.hasownproperty () => fn1.hasownProperty (“say”)

/* Use the Object tool method object.hasownProperty () to get the private property */
let obj = {
    name:'yzl'
}
console.log(obj.hasOwnProperty("name"))	//=>true

/ * - * /
const fn = function fn(){
    /* this.say = function say(){ console.log(1) } */
}
// Add to the prototype object
fn.prototype.say = function (){}
let fn1 = new fn();
console.log(fn1.hasOwnProperty("say"))	//=>false
{name:'fn', length:0, prototype:0x00, __proto__: function.__proto__}*/
console.log(fn1.hasOwnProperty("name"))	//=>name
Copy the code

I just want to check if it’s a property “private or public”

The target of the in test is an object (function is also an object) that can’t be found and can’t be traced down the prototype chain

function Fn(x, y) {
    let sum = 10;
    this.total = x + y;
    this.say = function () {
        console.log('My sum is:The ${this.total}`);
    };
}

let f1 = new Fn(10.20);
console.log('say' in f1); //=>true
console.log('hasOwnProperty' in f1); //=>true
console.log('sum' in f1); //=>false
/* Fn.__proto__.__proto__ runs to object. prototype */
console.log('hasOwnProperty' in Fn); //=>true
Copy the code

Requirement: Check whether this property is its public property.

Skip the prototype chain

Object.getprototypeof (obj) usage method

Getting a prototype object directly from an object (instance) is equivalent to fn.prototype

Object. GetPrototypeOf (obj) possible cause 1. 2. The Ie browser does not have __proto__ */
const fn = function fn(){
    this.toString = function (){
        console.log(1); }}let fn1 = new fn()

const hasPubProperty = function hasPubProperty(obj,attr){
    // @1 let proto = fn1.__proto__; // This is not compatible
    // @2 let proto = fn.prototype;
    let proto = Object.getPrototypeOf(obj);
    while(proto){
        if(proto.hasOwnProperty(attr)){
            return true
        }else{
            proto = Object.getPrototypeOf(proto); }}return false
}

console.log(hasPubProperty(fn1,"a"));
Copy the code

How do I detect if an object is an instance of the current constructor

instanceof

/* Check if fn1 is a new */ from the fn constructor
const fn = function fn(){}
let fn1 = new fn();
console.log(fn1 instanceof fn);	//=>true
console.log(fn1 instanceof Object);	//=>true
console.log(fn1 instanceof Function);	//=>true

console.log(fn instanceof Function);	//=>true
console.log(fn instanceof Object);	//=>true
Copy the code

Handwriting New method

Prototype @2 manually change the this of the fn function to point to the created instance object so that the function operates on the instance object @3 return return judgment + return instance object if no return is written or if return is a primitive type value + Return itself object if return is an object */


/ * -- - * /
Prototype const Dog = () => {this.name = name} */
function Dog(name) {
	this.name = name;
}

Dog.prototype.bark = function () {
    console.log('wangwang');
};
Dog.prototype.sayName = function () {
    console.log('my name is ' + this.name);
};

const _new = function _new(fn, ... args) {
    New 1(); new 1(); What an error
    if (typeoffn ! = ='function') throw new console.error(`${fn} is not a constructor`);
    /* @1 function name cannot be Symbol/BigInt new Symbol() error => _new(Symbol) error new BigInt() error => _new(BigInt) error => _new(BigInt) error => _new(BigInt) error @2 function must have prototype B: function(){}} ES6: function(){// ES6: function(){// ES6: function(){// ES6: function(){// ES6: function(){// ES6: function(){// ES6: function(){// ES6: function(){/
 if (/^(symbol|Bolean)$/i.test(fn.name) || typeof fn.prototype === "undefined") 
        throw new TypeError(`${fn.name}is not a constructor! `)
        Let obj = {}; let obj = {}; let obj = {}; obj.__proto__ = fn.prototype */
        let obj = Object.create(fn.prototype);
        /* @2 Change this to store the return value of the fn function */
        letresult = fn.call(obj, ... args);/* @3 difference three + if return is not written or a primitive value returns the instance object + if return is an object return itself */
    	if(result ! = ='undefined' && /^(function|object)$/i.test(typeof result)) return result
        return obj;
    }
let sanmao = _new(Dog, 'three hairs');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=> < span style = "max-width: 100%; clear: both;
console.log(sanmao instanceof Dog); //=>true

Copy the code

exercises

function Fn(x, y) {
    let sum = 10;
    this.total = x + y;
    this.say = function () {
        console.log('My sum is:The ${this.total}`);
    };
}
let res = Fn(10.20); // Normal function execution
let f1 = new Fn(10.20); // The constructor executes
let f2 = new Fn;
console.log(f1.sum);
console.log(f1.total);
console.log(f1.say === f2.say);
Copy the code
function Fn() {
    this.x = 100;
    this.y = 200;
    this.getX = function () {
        console.log(this.x);
    }
}
Fn.prototype.getX = function () {
    console.log(this.x);
};
Fn.prototype.getY = function () {
    console.log(this.y);
};
let f1 = new Fn;
let f2 = new Fn;
console.log(f1.getX === f2.getX);		//=>false
console.log(f1.getY === f2.getY);		//=>true
console.log(f1.__proto__.getY === Fn.prototype.getY);//=>true
console.log(f1.__proto__.getX === f2.getX);		//=>false
console.log(f1.getX === Fn.prototype.getX);		//=>false
console.log(f1.constructor);			/ / = > Fn functions
console.log(Fn.prototype.__proto__.constructor);	/ / = > Object
f1.getX();	/ / = > 100
f1.__proto__.getX();	//=>undefined
// y on the instance object
f2.getY();				/ / = > 200
// Find y on the prototype object
Fn.prototype.getY();	//=>undefined
Copy the code
function C1(name) {
    if (name) {
        this.name = name; }}function C2(name) {
    this.name = name;
}
function C3(name) {
    this.name = name || 'join';
}
C1.prototype.name = 'Tom';
C2.prototype.name = 'Tom';
C3.prototype.name = 'Tom';
alert((new C1().name) + (new C2().name) + (new C3().name));
//=>"Tom" + undefined + "join"	"Tomundefinedjoin"
Copy the code

Extension method based on built-in class prototype

Prototype -> array. prototype -> object. prototype */

(function(){
    const plus = function plus(num){
        return this + num
    };

    const minus = function minus(num){
        return this - num
    };

    ["plus"."minus"].forEach((v) = > {
        Number.prototype[v] = eval(v) }); }) ()let n = 10;
let m = n.plus(10).minus(5);
console.log(m);/ / = > 15 (10 + 10-5)
Copy the code

Refactor the following code based on the CLASS in ES6

/*--ES5--*/
function Modal(x,y){
    this.x=x;
    this.y=y;
}
Modal.prototype.z=10;
Modal.prototype.getX=function(){
    console.log(this.x);
}
Modal.prototype.getY=function(){
    console.log(this.y);
}
Modal.n=200;
Modal.setNumber=function(n){
    this.n=n;
};
let m = new Model(10.20);

/*--ES6 class--*/
class Model{
    This. XXX = XXX sets the private property of the instance */
    constructor(x,y){
        this.x = x;
        this.y = y; 
    }

    // This also sets the instance private properties
    z = 10;
	say = function say(){};    

    /* Extend the @1 method to the prototype object of the class. The @2 public attribute cannot be extended
    getX(){
        console.log(this.y)
    }
    getY(){
        console.log(this.y)
    }

	/* Treat it as an object and set static private properties and methods */
    static n = 200;
    static setNumber = function(n){
        this.n = n
    }
}

//ES6 sets public attributes for class objects
Model.prototype.z = 10;
let m = new Model(10.20);
Copy the code

Advanced: Three roles of a function

/* Function &object */
function Foo(){
    getName = function () {
       console.log(1);
    };
    return this;
}
Foo.getName = function () {
    console.log(2);
};
Foo.prototype.getName = function () {
    console.log(3);
};
var getName = function () {
    console.log(4);
};
function getName() {
    console.log(5);
}
Foo.getName();		/ / = > 2
getName();			/ / = > 4
Foo().getName();	/ / = > 1
getName();			/ / = > 1
new Foo.getName();	/ / = > 2
new Foo().getName();/ / = > 3
new new Foo().getName();/ / = > 3
Copy the code

1. What is the output result of the following code? Why?

Array.prototype.push = function(num){this[this.length] = num; this.length++; return this.length }; * /
let obj = {
    2: 3.3: 4.length: 2.push: Array.prototype.push
}
// This is obj so this.length = 2 this[this.length] = 1
obj.push(1);	
obj.push(2);
console.log(obj);
/* { 2: 1, 3: 2, length: 4, push: Array.prototype.push } */
Copy the code
let utils = (function(){
    function toArray(. args){
        /* @1 return args @2 return [...arguments] @3 return Array.from(arguments) @3 return Array.prototype.slice.call(arguments) @4 return [].slice.call(arguments) /* } return { toArray }; }) (); Let ary = utils. ToArray (10, 30); / / = > [10, 30] ary = utils. ToArray (' A ', 10, 30); / / = > [' A ', 10, 30]Copy the code
/* * * */
function Fn() {
    let a = 1;
    this.a = a;
}
Fn.prototype.say = function () {
    this.a = 2;
}
Fn.prototype = new Fn;
let f1 = new Fn;
​
Fn.prototype.b = function () {
    this.a = 3;
};
console.log(f1.a);
console.log(f1.prototype);
console.log(f1.b);
console.log(f1.hasOwnProperty('b'));
console.log('b' in f1);
console.log(f1.constructor == Fn);
Copy the code

Write queryURLParams methods that do the following (at least two scenarios)

#([^+=&?]) /#([^+=&?]) @ 2 +)/g of several URL key-value pairs/([^ =? # &] +) = ([^ =? # &] +)/g according to the param return value * /
String.prototype.queryURLParams = function queryURLParams(param) {
    let obj = {};
    this.replace(/ # (/ ^ + = &? +)/g.(_, $1) = > {
        obj["_HASH"] = $1
    })
    this.replace(/([^=?#&]+)=([^=?#&]+)/g.(_, $1, $2) = > {
        obj[$1] = $2;
    })

    if(param ! = ="undefined") return obj[param]
    return obj
}

/*-- traditional string concatenation --*/
String.prototype.queryURLParams = function queryURLParams(param){
    let str = this.split("/?") [1],
        obj = {};
    obj["_HASH"] = str.split("#") [1];
    str.split("#") [0].split("&").forEach((v,i) = > {
        let key = v.split("=") [0],
            value = v.split("=") [1];
            obj[key] = value;
    })
    if(param ! = ="undefined") return obj[param]
    return obj
}

/* Test results */
let url="http://www.zhufengpeixun.cn/?lx=1&from=wx#video";
console.log(url.queryURLParams("from")); //=>"wx"
console.log(url.queryURLParams("_HASH")); //=>"video"
Copy the code
Rewrite the call/apply/bind
/* The call @1 function is called in obj and this points to the bind @2 currization closure + call */
(function(){
    const call = function call(obj,... args){
        Object(obj);
        obj = obj || window;
        if(!/(function|object)/i.test(typeof obj)) obj = Object(obj);
        let _id = Symbol(),
            result;;
        obj[_id] = this; result = obj[_id](... args);// Delete it
        delete obj[_id];
        return result;
    };
   const apply = function apply(obj,args){
        obj = obj || window;
        Object(obj);
        if(!/(function|object)/i.test(typeof obj)) obj = Object(obj);
        let _id = Symbol(),
            result;;
        obj[_id] = this; result = obj[_id](... args);// Delete it
        delete obj[_id];
        return result;
    };
   const bind = function bind(obj,... args){
        obj = obj || window;
        let self = this;
        return function (. event){
            self.call(obj,...[...args,...event]);
        }
    };

    ["call"."apply"."bind"].forEach((v,i) = > {
        Function.prototype[v] = eval(v); }); }) ()let obj = {
    name:'yzl'
}

const fn = function(x,y){
    // console.log(this,x+y);
    this.x = x;
    this.y = y;
}

Call * / / * detection
fn.call(obj,10.20);
The apply * / / * detection
fn.apply(obj,[10.20]);
The bind * / / * detection
document.body.onclick = fn.bind(obj,10.20);
Copy the code

More than one call

/* fn1.call(fn2); @1 a call executes fn1,this refers to fn2 fn1.call.call(fn2,10,20,30); @2 Two or more calls execute fn2,this executes 10, with parameters 20/30 */
function fn1(){console.log(1); }function fn2(){console.log(2); } fn1.call(fn2);/ / = > 1
fn1.call.call(fn2);	/ / = > 2
Function.prototype.call(fn1); //=> Empty function returns undefined
Function.prototype.call.call(fn1);	/ / = > 1
Copy the code