原型/原型链/构造函数/实例/继承
-
凡是构造函数都有一个原型属性
prototype
凡是对象都有一个原型,通过
__proto__
可以访问原形,访问到的原型又是对象,那么如此下去,就会构成一个对象的序列,该结构称为原型链默认的原型链就是: 当前对象-->构造函数.prototype-->Object.prototype--null
注意: 原型和实例上都有一个
constructor
构造器指向构造函数Function.prototype.constructor === new Function().constructor
-
混合继承
-
构造函数继承:apply/call继承构造函数里面的属性和方法
const Person=function(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } const Student=function(name,age,sex,pro){ //this:实例对象 Person.apply(this,arguments);//子类继承父类上面所有的属性和方法 this.pro=pro; } Student.prototype=Person.prototype;//引用传递
-
原型继承
-
拷贝继承:原型是对象属性,浅拷贝的方式将父类原型上面的内容传递给子类。
const Person=function(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } const Student=function(name,age,sex,pro){ //this:实例对象 Person.apply(this,arguments);//子类继承父类上面所有的属性和方法 this.pro=pro; } Object.assign(Student.prototype,Person.prototype);
-
原型链继承:将父类的实例给子类的原型
Student.prototype=new Person();
缺点:父类将子类的构造函数覆盖了。
Student.prototype.constructor=Student;//重置构造函数
-
-
class继承
-
class person { constructor(name, age, sex) { //构造函数 this.name = name; this.age = age; this.sex = sex; } singing() { return `我的姓名是${this.name},我的年龄是${this.age},我是${this.sex}的`; } } class student extends person{ constructor(name,age,sex,pro){ super(name,age,sex);//父类 当做函数使用,代表父类的构造函数。 this.pro=pro; } }
- super当作函数调用时,继承父类的构造函数
- super作为对象时,在普通方法中指向父类的原型对象
-
-
数据类型判断
-
typeof
-
typeof 'a'; // string 有效 typeof 1; // number 有效 typeof true; //boolean 有效 typeof Symbol(); // symbol 有效 typeof undefined; //undefined 有效 typeof new Function(); // function 有效 typeof null; //object 无效 typeof [1] ; //object 无效 typeof new RegExp(); //object 无效 typeof new Date(); //object 无效
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型。
- 对于 null ,返回 object 类型。
- 对于 function 返回 function 类型。
-
-
instanceof
-
[] instanceof Array; // true new Date() instanceof Date;// true function Person(){}; new Person() instanceof Person;//true [] instanceof Object; // true new Date() instanceof Object;// true new Person instanceof Object;// true
- instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型
- 需要通过new关键字 对对象进行判断
- 对null和undefined判断时报错
-
-
constructor
-
var num = 12; console.log([].constructor); //Array console.log('string'.constructor); //string console.log(num.constructor); //number console.log(new Object().constructor); //object
- 对null和undefined判断时报错
-
-
toString
-
语法:Object.prototype.toString.call(value);
-
Object.prototype.toString.call('') ; // [object String] Object.prototype.toString.call(1) ; // [object Number] Object.prototype.toString.call(true) ; // [object Boolean] Object.prototype.toString.call(Symbol()); //[object Symbol] Object.prototype.toString.call(undefined) ; // [object Undefined] Object.prototype.toString.call(null) ; // [object Null] Object.prototype.toString.call(new Function()) ; // [object Function] Object.prototype.toString.call(new Date()) ; // [object Date] Object.prototype.toString.call([]) ; // [object Array] Object.prototype.toString.call(new RegExp()) ; // [object RegExp] Object.prototype.toString.call(new Error()) ; // [object Error] Object.prototype.toString.call(document) ; // [object HTMLDocument] Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用
-
闭包(作用域,作用域链)
- 主要作用:变量私有化,读取自身函数外部的变量(沿着作用域链寻找)
- 缺点:
- 闭包会让函数内部变量始终保存在内存中,需要手动释放资源;【解决办法:即将函数设置为null】
- 过多的闭包导致内存泄漏。
- 作用域:局部和全局,(ES6之后有块级作用域的概念)
Ajax的原生写法
-
新建ajax对象
let ajax = new XMLHttpRequest();
-
ajax对象的open()
ajax.open('get','http://localhost/HTML1909/JS1909/Day%2021/5.phparray.php',true); //open(请求方式get/post,接口地址,是否异步true异步/false同步)
-
ajax对象的send()
ajax.send();
-
ajax对象的事件--onreadystatechange监听就绪状态是否完成。
ajax.onreadystatechange=function(){ if(ajax.readyState===4){//请求完成 //ajax.responseText:ajax请求返回的内容就被存放到这个属性下面,返回获取的内容,string console.log(ajax.responseText); console.log(JSON.parse(ajax.responseText)); } }
-
如果是post还需要在open()后设置请求头
xmlhttp.setRequestHeader("content-type", "application/x-www-form-urlencoded")
对象深拷贝和浅拷贝
-
浅拷贝
-
Object.assign()
语法:Object.assign(target ,source);
var target = {}; var source = {a:1}; Object.assign(target ,source); console.log(target); //{a:1} source.a = 2; console.log(source); //{a:2} console.log(target); //{a:1}
-
扩展运算符
语法:var obj2 = {...obj};
var obj = {a:1,b:{c:1}} var obj2 = {...obj}; obj.a=2; console.log(obj); //{a:2,b:{c:1}} console.log(obj2); //{a:1,b:{c:1}} obj.b.c = 2; console.log(obj); //{a:2,b:{c:2}} console.log(obj2); //{a:1,b:{c:2}}
-
-
深拷贝
-
JSON.stringify(JSON.parse())
var obj1 = { a:1, b:[1,2,3] } var str = JSON.stringify(obj1) var obj2 = JSON.parse(str) console.log(obj2); //{a:1,b:[1,2,3]} obj1.a=2 obj1.b.push(4); console.log(obj1); //{a:2,b:[1,2,3,4]} console.log(obj2); //{a:1,b:[1,2,3]}
-
递归
var obj1 = { a:{ b:1 } }; function deepClone(obj) { var cloneObj = {}; //在堆内存中新建一个对象 for(var key in obj){ //遍历参数的键 if(typeof obj[key] ==='object'){ cloneObj[key] = deepClone(obj[key]) //值是对象就再次调用函数 }else{ cloneObj[key] = obj[key] //基本类型直接复制值 } } return cloneObj } var obj2 = deepClone(obj1); obj1.a.b = 2; console.log(obj2); //{a:{b:1}}
-