标签:argument 出现 空间 UNC ret 多态 names 逻辑 提高
供代码执行的运行环境即全局作用域
在浏览器打开页面的同时,也会形成两个虚拟的内存;
一个是栈内存,一个堆内存;
栈内存:1.提供代码运行环境2.存储基本数据类型值
堆内存:存储引用数据类型值;
//在全局作用域形成以后,在这个全局作用域会默认提供最大的window对象;
//全局变量:在全局作用域下定义的变量叫全局变量;
私有变量:在私有作用域下定义的变量
//var a=100;
//function fn(){
////在函数私有作用域中定义的变量,不会给window新增键值对;
////var b=10;
//var a=99;
//console.1og(a);//100函数里面可以访问函数外面的变量
//}
//fn();
//console.1og(b);
//函数执行会形成私有的作用域,会保护里面的私有变量不受外界的干扰;
let:let声明的变量不能给window新增键值对;
const声明的常量也不能新增键值对:
//const e=1;
//let d=1;
//console.log(d);
//1.私有作用域是在全局作用域下形成创建的;在全局作用域中包含私有的作用域;
//2.全局作用域不能访问私有作用域下的私有变量,但是私有作用域能够访问全局作用下变量
//3.如果私有作用域存在该私有变量,那么就不再向外获取
function fn(){
//私有作用域:是给函数体中的代码提供代码的运行环境的;
//和全局作用域,
///var a=1e;
a=11;
console.1og(10)
}
fn();
console.1og(a);
debugger;添加断点
过程:
//变量提升:在当前作用域下,代码执行之前,会首先把带var的和function进行提前声明,
带var的只声明,不赋值,
但是function不仅声明,而且还要赋值(定义);
那么这种机制就是变量提升的机制;先对function变量提升
//声明:通知了当前作用域有这么一个变量;
console.log(a);//undefined
console.log(b)
var a=100;b=99;
变量提升:在当前作用域下,代码执行之前,会首先把带var的和function进行提前声明,
带var的只声明,不赋值,
function不仅声明,而且还要赋值(定义);
那么这种机制就是变量提升的机制;先对function变量提升
function fn(){
console.1og(f);
return function f(){}
console.log(f)
]
var obj={
fn:(function(){
console.1og(100);
//;
return function(){
})()
console.1og(200)
obj.fn()
fn();//4
function fn(){
console.1og(1);
function fn(){
console.1og(2);
fn();//4
function fn(){
console.1og(3);
fn=100;
function fn(){
console.1og(4);
fn();报错
var fn=function(){};
(function(){})();
console.log(num);
1et num=18e;
console.1og(num);
var total=10;
function sum(){
var total=100;
return function(){
console.log(total);//undefined 100
//var total=1000;
}
var f=sum();//f接受到了sum返回的小函数:
f();
堆内存回收:
Gc垃圾回收机制;在浏览器内置了一个gc程序,这个程序会每隔一段时间执行一次;
1.标记法:浏览器每隔一段时间要对所有的空间地址类型进行检测,检查该地址是否被占用:如果没有占用,那么久立即回收掉
2.IE计数法:每当到间地址占用一次,该地址标识就会默认+1;如果不再占用,就会-1:如果标记计数为e:立即回收:
/栈内存回收==>作用域销毁;
栈内存回收==>作用域销毁;
立即销毁
【1】不销毁的作用域
1.返回一个引用的数据类型值
2.返回的值需要被外界接受
3 如果当前作用域有个空间地址,被函数体外的东西占用着,那么这个栈内存就不能销毁; olis占用了这个空间地址
function fn(){
olis[i]. onclick=function(){
}
}
fn()
1.在全局作用域,this指向window;this 和window是同一块空间地址:
console.log(this);//window window.
alert()
this.alert();
2.给元素的事件绑定的函数中的this,指向了当前被点击的那个元素:
box.onclick=function(){
//this:对象:
console.dir(this)}
3.普通函数执行:看函数执行前有没有“.”,如果要是没有,那么函数中的this指向window,
如果有“.”,那么点前面是谁,this就指向谁:跟在哪执行有关
var obj={
m:1,
fn:function(){
console.1og(this);
}//this就指向了obj;
var f=obj.fn;
console.1og(f==obj.fn);
obj.fn();
f();
4.自执行函数中this永远指向window:
(function(){
console.log(this);//window
})();
5.回调函数中的this一般都指向window;
6.构造函数中的this指向实例
7.calll,apply,bind 可以改变this指向:
基于call/apply/bind可以改变函数中this的指向(强行改变)
Function.prototype={
call
apply
bind
}
call的练习题
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
/* function call(context = window, ...args) {
context.$fn = this;
let result = context.$fn(...args);
delete context.$fn;
return result;
} => AAAFFF000*/
fn1.call(fn2); //=>执行的是FN1 =>1
fn1.call.call(fn2); //=>执行的是Fn2 =>2
Function.prototype.call(fn1); //空
Function.prototype.call.call(fn1); //=>1
总结:当执行一个call,则执行call前面的函数,但是this指向括号中
当执行两个及两个以上call,则执行括号中的函数
var a=1; 3
var obj1={
a:0, 1 2
fn1:(function(a){
a=1 2 3 4
this.a=a;
a++; 2
return function(){
this //obj //Windows
this.a=a++; 3
console.1og(a) 3 4
}
})(a)
};
obj1.fn1();
var fnl=objl.fn1;
fn1();
console.1og(a); 3
console.1og(obj1.a); 2
var n=2: 4 8
var obj{
n:3, 6
fn:(function(n){
n=2 4
n*=2;
this.n+=2;
var n=5: 6 7
return function(m){
m=3
this.n*=2;
console.1og(m+(++n)); 9 10
])(n)
var fn=obj.fn:
fn(3);
obj.fn(3);
console.1og(n,obj.n): 8 6
var num=1; 2 4
var obj={
num:2, 4
fn:(function(){
this.num*=2;
num +=3; NAN 1 3
var num=1; 1
return function(){
num+=2; 3 4 6 7
this.num+=2
console.1og(++num); 4 7
})()
};
var f= obj.fn;
f();
obj. fn();
console.1og(window. num, obj. num); 4 4
检测数据类型1:typeof
返回结果都是字符串
字符串中包含了对应的数据类型 "number"/"string"/"boolean"/"undefined"/"symbol"/"object"/"function"
【局限性】
* typeof null => "object" null不是对象,它是空对象指针
* 检测数据或者正则等特殊的对象,返回结果都是"object",所以无法基于typeof判断是数组还是正则
检测数据类型2/3:instanceof / constructor 类似的
检测某个实例是否属于这个类
他检测的底层机制:所有出现在其原型链上的类,检测结果都是TRUE
【局限性】
* 由于可以基于__proto__或者prototype改动原型链的动向,所以基于instanceof检测出来的结果并不一定是准确的
* 基本数据类型的值,连对象都不是,更没有__proto__,虽说也是所属类的实例,在JS中也可以调取所属类原型上的方法,但是instanceof是不认的
arr.instanceof == Array
arr.constructor==Array
检测数据类型4:Object.prototype.toString.call([value]) /
({}).toString.call([value]) 常用方法
({}).toString.call("stknf")
1.表现形式
var obj={
XXx:XXX,
}
2.作用
=>把描述同一件事务的属性和特征进行“分组、归类”(存储在同一个堆内存空间中),因此避免了全局变量之间的冲突和污染
3.单例设计模式命名的由来
*=>每一个命名空间都是Js 中object这个内置基类的实例,而实例之间是相互独立互不干扰的,所以我们称它为单例:”
【1】.在给命名空间赋值的时候,不是直接赋值一个对象,而是先执行匿名函数,形成一个私有作用域AA(不销毁的栈内存),在AA中创建一个堆内存,把堆内存地址赋值给命名空间
【2】这种模式的好处:我们完全可以在AA中创造很多内容(变量or函数,哪些需要供外面调取使用的,我们暴露到返回的对象中(模块化实现的一种思想)
var nameSpace=(function(){
function fn(){
}
return {
fn:fn
}
})()
模块化开发
*模块化开发
*1.团风协作开发的时候,会把产品按照功能板块进行划分,每一个功能板块有专人负责开发
*2.把各个版块之间公用的部份进行提取封装,后期在想实现这些功能,直接的调。
取引用即可(模块封装)
var weatherRender=(function(){
var fn=function(){
};
return{
init:function(){
fn();//=>调取自己模块中的方法直接调取使用即可
skipRender.fn();//=>调取别人模块中的方法
})();
weatherRender.init();
工厂模式(Factory Pattern)
1.把实现相同功能的代码进行“封装”,以此来实现“批量生产”(后期要实现这个功能,我们只需要执行函数即可)
2.“低剩合高内聚”:减少页面中的冗余代码,提高代码的重复使用到
function createPerson(name, age){
var obj={};
obj. name=name;
obj. age=age;
return obj;
}
面向对象编程,需要我们掌握:“对象、类、实例”的概念
对象:万物对象
类:对象的具体细分(按照功能特点进行分类:大类、小类)
实例:类中具体的一个事物(拿出类别中的具体一个实例进行研究,那当前类别下的其它实例也具备这些特点和特征)
js本身基于面向对象编程
基于构造函数创建自定义类(constructor)
在普通函数执行的基础上"new xxx()”,这样就不是普通函数。执行了,而是构造函数执行,当前的函数名称之为“类名”,接收的返回结果是当前类的一个实例
自己创造类名,最好第一个单词大写。
function Fn(){
}
var f =new Fn()
实例之间是独立分开,互不干扰
JS创建值两种方式
1.字面量表达式
2.构造函数模式
var obj1={ }
var obj2=new Object()
var obj={};//->字面量方式
var obi=new Object();//->构造函数模式
Fn() => 普通函数执行
=>不管是哪一种方式创造出来的都是object类的实例,而实例之间
是独立分开的,所以 var xxx={)这种模式就是Js中的单例模式
基本数据类型基于两种不同的模式创建出来的值是不一样的
基于字面量方式创建出来的值是 基本类型值
基于构造函数创建出来的值是 引用类型
NUM2是数字类的实例,NUM1也是数字类的实例,它只是JS表达数字的方式之一,都可以使用数字类提供的属性和方法
var numl=12;
var num2=new Number(12);
console. log(typeof numl);//=>"number"
console. log(typeof num2);//->"object"
普通函数执行
1.形成一个私有的作用域
2.形参赋值
3.变量提升
4.代码执行
5.栈内存释放问题
构造函数执行原理
console. log(f instanceof Fn);//=>TRUE
console. log(f instanceof Array);//=>FALSE
console. log(‘m‘ in f)://=>TRUE
console. log(‘n‘ in f);//=>FALSE
console. log(f. hasOwnProperty(‘m‘));//=>true
console. log(f. hasOwnProperty(‘n‘));
【函数]
普通函数、类(所有的类:内置类、自己创建的类)
【对象]
普通对象、数组、正则、Math、arguments..…
实例是对象类型的(除了基本类型的字面量创建的值)
prototype的值也是对象类型的
函数也是对象类型的
【原型链:】
它是一种基于_proto向上查找的机制。当我们操作实例的某个属性或者方法的时候,首先找自己空间中私有的属性或者方法
1.找到了,则结束查找,使用自己私有的即可
2.没有找到,则基于_proto找所属类的prototype,如果找到就用这个公有的,如果没找到,基于prototype上的_proto继续向上查找,一直找到Object.prototype的原型为止,如果在没有,操作的属性或者方法不存在 返回undefined
【举例】
### 类的继承和多态
类的多态:重载和重写 (无)
JAVA中重载:函数名相同,但是传参类型、数量不同或者返回值不一样,这相当与把一个函数重载了 (JS中没有类似于后台语言中的重载机制:JS中的重载只的是同一个方法,根据传参不同,实现不同的业务逻辑) 重写:子类重写父类上的方法
继承:子类继承父类中的属性和方法(JS中的继承机制和其它后台语言是不一样的,有自己的独特处理方式)
方案一:原型继承 (B子类 => A父类)
子类的原型指向父类的一个实例
function A() {
this.x = 100;
}
A.prototype.getX = function getX() {
console.log(this.x);
};
function B() {
this.y = 200;
}
B.prototype.sum=function(){}
B.prototype = new A();
B.prototype.getY = function getY() {
console.log(this.y);
};
let b = new B;
function A() {
this.x = 100;
}
A.prototype.getX = function getX() {
console.log(this.x);
};
function B() {
//CALL继承
A.call(this); //=>this.x = 100; b.x=100;
this.y = 200;
}
B.prototype.getY = function getY() {
console.log(this.y);
};
let b = new B;
console.log(b);
function A() {
this.x = 100;
}
A.prototype.getX = function getX() {
console.log(this.x);
};
function B() {
A.call(this);
this.y = 200;
}
//=>Object.create(OBJ) 创建一个空对象,让其__proto__指向OBJ(把OBJ作为空对象的原型)
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
B.prototype.getY = function getY() {
console.log(this.y);
};
let b = new B();
console.log(b);
* ES6创建类用class
class A {
constructor() {
this.x = 100;
}
getX() {
console.log(this.x);
}
}
//=>extends继承和寄生组合继承基本类似
class B extends A {
constructor() {
super(100); //=>一但使用extends实现继承,只要自己写了constructor,就必须写super <=> A.call(this,100)
this.y = 200;
}
getY() {
console.log(this.y);
}
}
标签:argument 出现 空间 UNC ret 多态 names 逻辑 提高
原文地址:https://www.cnblogs.com/smilestudio/p/12979683.html