number、string、boolean、null、undefined javascript
object:{}、[ ]、/$/、Date
function html
当浏览器加载html页面的时候,首先会提供一个全局jsdiam执行的环境java
var num = 12;
var obj = {name:"wjw",age:7);
function fn(){
console.log("勿忘初心方得始终")
}
console.log(fn); // 把整个函数的定义部分(函数自己在控制台输出)
console.log(fn()); //把当前函数执行的返回结果(return后面写的是啥,返回就是啥,若是没有return,默认返回undefined)
复制代码
在当前的做用域中,js代码执行以前,浏览器首先会默认的把全部带var和function的进行提早的声明或者定义浏览器
var num ;
复制代码
告诉浏览器在全局做用域中有一个num的变量了
若是一个变量只是声明了,可是没有进行变量的定义,那就是undefined
bash
num = 12 //给咱们的变量进行赋值
复制代码
在预解释的时候只是提早的声明闭包
在预解释的时候,提早的声明+定义都完成了dom
对于带var和function关键的预解释的操做仍是不同函数
fn(100,200);//能够在上面执行,由于预解释的时候,声明+定义已经完成了
function fn(num1,num2){
var total = num1 + num2;
console.log(total);
}
复制代码
例如:开始只对window下得进行预解释,只有函数执行的时候才会对函数的进行预解释ui
用来提供一个js执行的环境 -> 做用域(全局的做用域,私有)this
用来存储引用数据类型的值 -> 对象存储属性名和属性值,函数存储的是代码字符串
在私有做用域中,咱们代码执行的时候遇到一个变量,首先咱们须要肯定当前它,是不是私有变量,若是是私有的变量,那么和外面的任何东西都没有关系;若是不是私有的,则往当前做用域上级做用域进行查找,若是上级做用域也没有则继续查找,一直找到window为止..
(直接目的:让函数体重的代码执行),首先会造成一个新的私有的做用域
1.若是有形参,先给形参赋值
2.进行私有做用域中的预解释
3.私有做用域中的代码从上到下执行
console.log(total); // undefined
var total = 0;
function fn(num1,num2){
console.log(total); // total 不是私有的,找全局下的total,也就是在这里出现全部的total其实应该都是
var total = num1 + num2;// 全局的total=300
console.log(total);// 300
}
fn(100,200);
console.log(total);// 300
复制代码
函数造成一个新的私有的做用域保护了里面的私有变量不受外界的干扰(修改不了私有的,私有的也修改不了外面的
在全局做用域中,带var和不带var的关系?
区别:带var的能够进行预解释,因此在赋值的前面执行不会报错;不带var的是不能进行预解释的,在前面执行会报错
console.log(num);//undefined
var num = 12;
console.log(num2); // Uncaught ReferenceError:num2 is no defined
num2 = 12;
复制代码
关系:num = 12 ->至关于给window增长了一个叫作num的属性名,属性值12
var num =12 ->首先它至关于给全局做用域增长了一个全局变量num,可是不只如此,它也至关于给window增长了一个属性名怒,属性值12
var num = 12;
console.log(num); // 12
num2 = 12;
console.log(num2);// 12 window.num2
复制代码
私有做用域中出现的一个变量不是私有的,则往上级做用域进行查找,上级没有则继续向上级查询,一直找到window为止
funtciont fn(){
console.log(total1); // Uncaught ReferenceError:num2 is no defined
total = 100;
}
fn();
console.log(total1)
复制代码
js中若是不进行任何特殊处理的状况下,上面的代码报错,下面的代码都不在执行了
in "num" in window 判断num是否为window这个对象的一个属性,是的话返回true,不是返回flase
console.log("name" in obj)
复制代码
window的预解释:var num - > window num
if(!("num") in window){ // “num” in window ->true
var num = 12
}
console.log(num) -> undefind
复制代码
匿名函数值函数表达式:把函数定义跌部分当作一个值赋值给咱们的变量(元素的某一个事件)
window下的预解释 var fn;
fn(); // undefined
var fn = function(){
conslole.log("ok")
}
fun(); // ok
function fn(){
console.log("ok")
}
fn(); // ok
复制代码
自执行函数: 定义和执行的一块儿完成了
(function (params) {})(100);
~function (params) {}(100);
+function (params) {}(100);
-function (params) {}(100);
!function (params) {}(100);
复制代码
function fn(){
// 预解释:var num;
console.log(num); // ->undefined
return function(){}; // -> 不预解释
var num = 100
}
fun();
复制代码
预解释:var fn ; window.fn; fn-xxxfff000 window.fn-xxxfff00
var fn = 13;
function fn() {
console.log("ok");
}
复制代码
window 预解释 声明+定义 fn = xxxfff11 声明 var fn; (不须要从新声明) 声明(不重复进行)+定义 fn = xxxfff222 fn = xxxfff22
fn(); // ->2
function fn() {console.log(1)}; //-> 2
fn(); // 2
var fn = 10;
fn (); // error 终止了
function fn() {console.log(2)};
fn();
复制代码
看当前函数是哪一个做用域下定义的,那么它的上级做用域就是谁
let num =12;
function fn() {
var num = 120;
return function () {
console.log('====================================');
console.log(num);
console.log('====================================');
}
}
var f = fn();
f(); // 这样就执行了第1次
~function() {
var num = 1200;
f(); // 这样就执行了第2次
}()
复制代码
var f = fn()就是把函数fn的运行返回结果赋值给f,fn函数返回的是一个函数,该返回函数的上级做用域为函数fn
的私有做用域,因此运行f函数console.log(num),num不是f私有做用域的私有变量,须要在上级做用域找,fn的私有做用域含有变量
num,因此都输出的num为120。
总结一下,执行函数的做用主要为匿名和自动执行,代码在被解释时就已经在运行了。
(function(){ /* code */ }());
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
~function(a) {
console.log('====================================');
console.log(a);
console.log('====================================');
}(10)
复制代码
对象数据类型或者函数数据类型在定义的时候首先都会开辟一个堆内存,堆内存有一个引用的地址,若是外面有变量等知道这个地址,外面就说这个内存被占用,就不能销毁。
var obj1 = {name:"张三"};
var obj2 = obj1;
复制代码
咱们想要让堆内存释放/销毁,只须要吧全部引用它的变量值赋值为null便可,若是当前的堆内存没有任何东西呗占用了,那么浏览器会在空间的时候把它销毁...
obj1 = null;
obj2 = null;
复制代码
通常状况下,函数执行会造成一个新的私有的做用域,当私有做用域中的代码执行完成后,咱们当前做用域都会主动的进行释放和销毁
可是仍是存在特殊的状况的:
当前私有做用域中的部份内存被做用域之外的东西占用了,那么当前的这个做用域就不能销毁了
a.函数执行返回了一个引用数据类型的值,而且在函数的外面被一个其余的东西给接收了,这种状况下造成的私有做用域都不会销毁
function fn(){
var num = 100;
return function(){
num++;
console.log(num);
}
}
var f = fn(); // fn执行造成这个私有的做用域就不能再销毁了
复制代码
b.在一个私有的做用域中给dom元素的事件绑定方法,通常状况下咱们的私有做用域都不会销毁
var oDLv = document.getElementById('div1');
~function(){
oDLv.onclick = function(){
}
}() // 当前自执行函数造成一个私有的做用域也不销毁
复制代码
c.下述状况属于不当即销毁->fn返回的函数没有被其它的东西占有,可是还须要执行一次呢,因此暂时不销毁,当返回的值执行完成后,浏览器会在空闲的时候把它销毁
function fn(){
var num = 100;
return function(){
}
}
复制代码
都是自身累加1,在和其余的值进行运算的时候是有区别的
var i = 5;
console.log(1+i++);//6 i=6
console.log(1+(++i));//6 i=7
console.log(2+(i++)+(++i)+(++i)+(i++));//38
console.log(i);// 9
复制代码
function fn(){
var i = 10;
return function (n){
console.log(n+(++i));
}
}
var f = fn();
f(10);// 21
f(20);// 32
fn()(10);// 21
fn()(20);// 31
复制代码
function fn(){
var i = 10;
return function (n){
console.log(n+(++i));
}
}
var f = fn(13);
f(12);// 25
f(24);// 28
fn(15)(12);// 27
fn(16)(13);// 29
复制代码
咱们在js中主要研究的都是函数中的this
js中的this表明的是当前行为执行的主体,js中的context表明的是当前行为的环境(区域)
例如:吴佳玮在沙县吃蛋炒饼,this->吴佳玮 context->沙县小吃
function 吃饭(){
this->吴佳玮
}
吴佳玮.吃饭();
~function(){
吴佳玮.吃饭();
}();
复制代码
this是谁和函数在哪定义的和在哪执行的都没有任何关系:如何的区分 this呢
function fn(){
console.log(this);
}
var obj ={
fn:fn
};
fn(); // this->window
obj.fn();// this->obj
function sum(){
fn();
}
sum();
复制代码
<div id="div1">有本事点我啊~~</div>
...
<script> document.getElementById("div1").onclick = fn;//fn中的this是#div1 document.getElementById("div1").onclick = fucntion(){ // this->#div1 fn(); // this->window } </script>
复制代码
var num = 20;
var obj = {
num:30,
fn:(function(num){
this.num *=3;
num+=15;
var num = 45;
return function(){
this.num *=4;
num+=20;
console.log(num);
}
})(num) // 全局变量num的值20赋值给自执行函数的形参,而不是obj下的30,若是想是obj下的30,咱们须要写obj.num
}
var fn = obj.fn;
fn();
obj.fn();
复制代码
var oBth = document.getElementById("btn");
var spanNum = document.getElementById("spanNum")
// 利用全局做用域不销毁原理,把须要的数字定义为全局的变量
var count = 0;
oBtn.onclick = fucntion(){
count++;
spanNum.innerHTML = cont;
}
// 弊端:在项目中为防止全局变量之间冲突,咱们通常是禁止或者减小使用全局变量的使用
// 本身造成一个不销毁的私有做用域来保存咱们须要累加的数字
复制代码
二、 利用innerHTML的方式处理,每一次点击时候都先到页面中获取最新的值,而后累加,最后把累加的结果从新放回去
var oBth = document.getElementById("btn");
var spanNum = document.getElementById("spanNum")
//
oBtn.onclick = fucntion(){
spanNum.innerHTML++;
}
// 弊端:每一次吧页面中的内容先转换为字符串而后再累加,累加玩以后从新添加回去,
// 当从新的添加的时候浏览器重新的渲染一下
复制代码
三、利用自定义属性存储(推荐)
oBth.count = 0;
oBth.onclick = function(){
// spanNum.innerHTML获取页面中的内容返回的是一个字符串
spanNum.innerHTML = ++this.count;
}
复制代码