弱类型语言,没有保护性变量,没有私有变量,没有共有性变量。没有接口,虚函数。
JS中主动回收”。没有GC 的概念 GC:垃圾回收机制
类
对象是类的具象化体现 (抽象事物的具体表现)
类是对象的抽象化表现 (不是具体表现某一个的,抽象化表示该类事物)(人类的类别,个体)
类;父类;子类;基类;超类。
就相当于模型,本身就是一个 对象。这个类 (对象)的属性和方法,就是该类静态属性和静态方法(当然只能调用该类(对象)的内容),与别的内容没有关联。
这个类的抽象属性和方法(可以将这个属性方法应用于实例化的对象)。称为动态属性方法。只能被该类实例化的对象所调用,类自身(对象)是不能调用的。
类实例化的对象属性可以更改,不会影响到其他对象。
静态方法禁止写this,(在JS 中静态方法的this就是类名(对象)
动态可以调用静态方法和属性。
任何对象调用的静态方法和静态属性值都是相同的
子类的父类是超类
super():调用父类的构造函数。会将该超类所有动态属性和方法继承给当前子类。
除了基类以外任何类别都有父类 (js中的基类是Object)
万物皆对象
如果没有继承对象,默认继承Object
ES6:
/ class Box{
// constructor(){
当new的时候就会执行constructor函数
ES5:
constructor 构造函数就是根据类创建对象的入口函数
函数名大写,执行函数 ,this就是window
对象:
新建对象:
构造函数法
var obj=new object();
字面量式创建
var obj={}
obj设置自己的对象属性,修改时就不会改变
根据对象创建对象
var obj1=Object.create(obj);
以传入的对象为原型基础,
protype:原型,是针对类描述的原型。是指动态属性和方法集合
proto:原型链 是针对对象来描述的原型链。
proto:原型链(继承链):不可遍历,不可枚举。 引用关系
对象中直接描述的属性(对象属性),在原型链下描述的属性都是原型属性。
当获取对象属性时,如果有该对象属性,直接返回该对象属性,如果没有该对象属性,返回距离该对象顶部最近的原型属性。
当直接设置对象的属性时,设置为对象的对象属性,不会覆盖原型属性值。
对象的__proto__原型链和对象的类的prototype原型一样.
原型:一旦使用new来实例化函数时,这个函数就是类名,也是这个类的构造函数。
只有类的原型protype上面描述的属性和方法,对象的__proto__中才会有该属性的方法。
对象属性分为对象属性和原型属性
判断该属性是否是对象的对象属性:hasOwnProperty
判断某个对象是否是另一个对象的原型链中的对象:isPrototypeOf
判断该属性是否是可枚举属性:propertyIsEnumerable
给所有标签添加的属性和方法(添加以后执行)
HTMLElement.prototype
原型链
原型链属性,对象属性都可以继承。
ES6描述的属性都是对象属性,没有原型属性。
ES6如果需要设置原型属性,就必须设置ES5的设置方式。
通过构造函数传参并且赋值给对象属性,这种方式就是构造函数创建对象是设置属性。
this 是实例化
new对象的构造函数,就意味着创建了一个相同类型的对象。
原型链中的属性相当于给对象做了初始化属性的赋值。
对象的属性可以自己添加。
原型的属性只能添加到原型上。
对象中有对象属性和原型链属性,获取属性,如果对象属性不存在,就会寻找离他最近的原型链属性。设置属性时,设置的都是对象属性,不能设置原型链属性
DOM元素不能使用new构造函数的方式创建,只能使用document.createElement()创建。
接口不可以new。
对象没有forEach循环,可以增加。
for (按照下标循环)(空元素也循环) 根据length属性循环,如果length是对象属性,则根据该值循环,如果是原型属性,对象属性中没有,就会循环原型上的对应元素。
for in (按照属性循环)(包括下标,空元素不循环),如果内容有多少,就循环到所有内容,包括原型下的可枚举属性和元素。
**delete:**删除对象下的属性
不可删除属性是不能进行删除,(Object.defineProerty(configurable:false))
冻结的对象不可删除。
全局变量不能删除
delete arr.length:不能删除。
使用for循环可以遍历,for in 不可以遍历
window下定义的属性不能删除
Object.assign():ES6的复制。(只能复制可枚举属性(for in遍历的就是可枚举))
ES6中的复制,浅复制。这种复制方式,保留了目标对象上原有的属性,要复制对象所有属性都是添加在目标对象上;如果有多个对象复制时,相同的属性就会覆盖前面的。
不能复制不可枚举属性。(原型链的属性不能复制(原型链是不可枚举属性))
浅复制:
for in:遍历复制
Object.assign();保留新对象属性
var obj1={…obj}:不保留原对象的属性内容(原有的覆盖掉,形成新的引用地址)
深复制:
JSON:利用JSON复制可以将源对象转换为字符串,在转换为新对象
如果新对象有属性,不保留(不能转换不可遍历属性,因此也不能复制所有内容)
对象属性:
作为对象的私有变量使用
Object.defineProperty(要定义属性的对象;属性名;属性的描述对象)
属性名是对象的话就强制转换为字符串【object,object】
当Symbol作为对象属性时,不会转换为字符串
6个描述对象
configurable:true:(是否可删除该属性) flase:是不可删除(不能重新定义属性)
enumerable:tue:(是否可枚举)flase不可以枚举(不能同for in 遍历,Object.assign复制)
writable:true:是否可写,是否可以修改(默认为false,只读)
value:10(当前属性的值)
(淡紫色不可枚举属性)
如果使用setter和getter就不能设置value和writable
setter访问器属性
set:function(value){//设置属性执行方法
this._属性名=value;
}
getter访问器属性
get:function(){
return this._属性名;
}
enumerable:false时,不能复制,不可枚举(可以调用,也可以修改和删除)
当使用writable设为false时,该对象的属性值不可以修改
value:设置了时,不能删除,不能修改,不能枚举
获取对象属性
ES5和ES6不能直接设置常量
Object.defineProperty:用在设置对象的某个属性或方法不能够被遍历,删除,修改。
Object.getOwnPropertyNames
获取对象下所有属性名和方法名,返回这个名称组成的数组。不包括__proto__原型链
Object.getOwnPropertyDescriptor
获取对象下某个属性的描述对象
Object.defineProperties
可以设置多个属性,也可以设置函数
对象的深复制
根据该类型进行创建,然后复制。参数通过循环遍历的方式(for in)带进去
Object.freeze:(冻结)
冻结后元素不可以删除不可修改
Object.isFrozen(obj):判断对象是否被冻结
var bool=Object.is()
等同于===
Object.isExtensible(obj)
true: 判断该对象是否可以扩展
false: 当冻结后就不可以扩展了
call和apply
call:执行函数
call代理。
proxy:代理
var obj={};
fn.call(obj,3,5);
console.log(obj);
将obj带入函数中替换其中this指向,this–》带入的obj了。
如果函数中没有this,使用call和aplly就没有任何意义。
不同点:
call:是一个一个传入,apply是以数组传入。
var divs=document.getElementsByTagName("div");
var arr=Array.prototype.slice.call(div);//将类数组转换为数组
如果函数中没有this,使用call和apply就没有任何意义。
如果带入的是nall,将会把原来this的执行重新固定指向window
apply和call一样但是函数中的参数是以数组形式给入。
bind
绑定函数中this的指向为某个对象,这个函数不会立即执行,当下次调用该函数时,this就是被绑定的对象了,主要用于回调函数的this绑定,事件函数。
当将事件函数中的this替换成需要对象时,e.currentTarget就是被侦听对象。
bind就是将函数吗、里面的this替代为我们需要的对象,并且返回
新函数就是原来的函数不是同一个内容。
函数
定义函数时,是有作用范围。
参数虽然是局部变量,但是优先级低于函数中的函数。
传参实际早于函数内的函数定义,传完参数后,函数内的函数会覆盖该参数。
参数–定义内部函数—从当前函数最开始执行语句
函数的执行:
1,直接执行
2,通过call带入执行
自执行函数,只执行一次
(function fn1(){
})();
删除函数
fn=null;
ES6中函数的参数可以设置默认值,可以使用。。。arg设置多个参数
函数的参数就是局部变量,
arguments:参数列表
arguments.callee:当前函数
arguments.callee.caller:调用当前函数的函数。
return
返回一个数据。
工厂模式:
单例模式:
将传入的参数返回。
返回函数内的私密对象。
返回回调函数的结果。
通过解构赋值将返回的数组解构成多个变量。
函数内返回一个函数。
this指向
全局中的this,
ES5和ES6变量定义不同,this就有变化
使用var定义的变量将会绑定在window属性下
当使用let定义变量,变量具备块的范围性,因此,this虽然是window,但是不能调用到let设置的变量
全局中使用function定义的函数也可以通过this函数调用
1,window
当时用数组的方法时,桥接模式中forEach,map,sort,reduce,filter,some,setInterval,setTimeout,
2, 事件侦听的对象,this指向被侦听的对象。
3,call,apply,bind.替代函数中this指向 。this是window
4,对象中的this,只能使用在对象的方法中,不能使用在对象的属性中。this指向该对象
5,ES6中箭头函数的this,this重新定向为箭头函数外this的指向。
6,ES6中类的this, 构造函数中this,指使用new Box()产成的对象,this.a就是给这个产生的对象增加一个a属性。 在静态方法中不适用this,但是js中可以调用,这里的this是Box类自身。
5,ES5 中类的this指向。(当使用new构造函数时,构造函数就会被执行,构造函数中的this就是当前实例化的对象)(当对象调用方法play时,这个方法的this就是当前这个对象)
// function Box(){
// // 这里的this就是new出的对象
// this.a=3;
// }
// // 这个就是动态方法
// Box.prototype.play=function(){
// this.a*=3;
// // this 那个对象执行play方法,this就是那个对象
// console.log(this.a);
// }
// // 这个就是static的静态方法
// Box.plays=function(){
// console.log(this);
// // this就是Box这个函数
// }
// var b=new Box();
// b.play();
// Box.plays();
逐帧动画:
animation();
function animation(){
requestAnimationFrame(animation);//每帧执行一次这个函数。
console.log(this);
set和get
是将数据从外向内传入。(访问器 )
新建对象时。(ES5)
ES5
ES6:
set函数中有且仅有一个参数,将这个参数存储在当前对象的一个临时变量中。
get函数没有参数,并且最后返回存储的临时变量
小案例:上下左右BABA
如果只写get,表示该属性只读不可写。
如果只有set,只能设置值,不能获取值
set get本身没有属性,它是一个介于属性和方法之间的内容
属性直接获取值和直接设置等于值,还有拥有方法的可以执行多条语句
//方法操作可以传递多个参数,但是setget只能传递一个值
// // 主动存储,也可以主动获取
// obj.num=3;
// console.log(obj.num);
// 当对象已经创建,需要给对象增加setget方法时,
我们使用Object.defineProperty和Object.defineProperties
既可以用于存储,又可以用于执行某些语句。
set方法,就是设置这个属性值,调用set方法。通常来说set方法都有value参数,并且我们会将value参数另外存储在一个全局的临时变量中,如果不写set方法,仅写了get方法,意味着这个属性不可写(只读)
get方法,就是获取这个属性值,调用get方法。get方法必须要有一个return来返回这个获取的值,存储的变量值,并且这个return一定是在get方法。
上面这种对象中写入set,get方法都是在定义对象时来写的,如果对象已经有了就不能使用上面的方法
数据结构
将数据以什么的结构存储。
数组:(所谓数组,是无序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。)键对应值的方式存储。key对应value。
集(Object,就是集。多重集就是复杂的对象)
链表:
树
set,对象,map
闭包:
目的:为了解决具备一个局部可存储的私有变量
有权访问另一个函数作用域中的变量的函数。
特点:函数套函数,函数内部可以引用外部的参数和变量,参数和变量不会被垃圾回收机制回收。
私有变量:外部不能调用,内部执行完成不销毁,存储后,还能继续操作。
缺点:内存泄漏
返回对象
回调
事件本身就是回调函数。通过函数参数传递到其他代码的,某一块可执行代码的引用。
回调一般用于先解决某些事情后再做另外一个函数的内容处理
使用参数传入回调函数目的是可以执行不同需求
递归
:用于树型结构的深遍历。
继承
ES6的继承:
原型式继承:
html页面
export default class… extends
super:执行超类的构造函数。
override:重写这个方法时会覆盖父类的该方法
super.play:执行超类play方法。
解决代码重复,封装。
ES5优缺点:多执行了一次构造函数,原型继承时, 只能继承原型上的继承,不能继承超类的构造函数 ,
寄生式继承:添加子类内容时得一个一个添加
设计模式:
23种设计模式,
单例模式类的单例模式,可以在任意位置调用该方法获取这个唯一存储的对象。用于(管理器,存储器)保证一个类仅仅有一个实例,并提供一个访问他的全局访问点。(只创建一个)
工厂模式 创建直接return出来的
享元模式 碎片容器
代理模式 Proxy
观察者模式是这样一种设计模式。一个被称作被观察者的对象,维护一组被称为观察者的对象,这些对象依赖于被观察者,被观察者自动将自身的状态的任何变化通知给它们。当一个被观察者需要将一些变化通知给观察者的时候,它将采用广播的方式,这条广播可能包含特定于这条通知的一些数据。当特定的观察者不再需要接受来自于它所注册的被观察者的通知的时候,被观察者可以将其从所维护的组中删除。通俗点理解,就是面试官是被观察者,而等待通知的人是观察者。
被观察者的异变 ,观察者将派发出有关于被观察者的事件。
**桥接模式:**桥接模式就是将实现部分和抽象部分分离开来,以便两者可以独立的变化。在实现api的时候,桥接模式非常常用。可以看到,forEach函数并不关心fn里面的具体实现. fn里面的逻辑也不会被forEach函数的改写影响.
重写
forEach,
map
slice方法
filter
some,every
reduce
(initValue目的为了初始化值)
},0): 初始值,从0 开始加
sort:排序
a-b= j j+1
len-1
bind:
拖拽
(function(){
// var offPoint = {}
// var elem;
// Object.defineProperty(HTMLElement.prototype, "drag", {
// set: function (value) {
// this._drag = value;
// if (value) {
// this.style.position = "absolute";
// this.addEventListener("mousedown", mouseHandler);
// } else {
// this.style.position = "static";
// this.removeEventListener("mousedown", mouseHandler);
// }
// },
// get: function () {
// return this._drag;
// }
// })
// function mouseHandler(e) {
// if (e.type === "mousedown") {
// offPoint.x = e.offsetX;
// offPoint.y = e.offsetY;
// elem = this;
// document.addEventListener("mousemove", mouseHandler);
// document.addEventListener("mouseup", mouseHandler);
// } else if (e.type === "mousemove") {
// elem.style.left = e.clientX - offPoint.x + "px";
// elem.style.top = e.clientY - offPoint.y + "px";
// } else if (e.type === "mouseup") {
// document.removeEventListener("mousemove", mouseHandler);
// document.removeEventListener("mouseup", mouseHandler);
// }
// }
// })();
// var bool=false;
// var div = document.querySelector("div");
// var bn=document.querySelector("button");
// bn.drag=true;
// bn.addEventListener("click",clickHandler);
// function clickHandler(e){
// bool=!bool;
// div.drag=bool;
// }