原型与原型链及this

声明:下面说的对象是指 object Array Function 除 null 以外
1 任何对象 都可以做自由添加属性

var obj = {a:10, b:1}
obj.qq = "123456";
//Object {a: 10, b: 1, qq: "123456"}

2 在JavaScript中任何对象都会有_proto_ 属性 (隐式原型)

3 在JavaScript中函数对象 都会有prototype属性 (显式原型)

4 任意对象的_proto_ (隐式原型)指向 其构造函数的prototype(显式原型)

//安装规范 构造函数名 采用大驼峰命名方式
var Foo = function () {this.name = "long";this.age = "10";
}
var foo = new Foo();
foo.__proto__ === Foo.prototype
//true

5 任何一个函数调用其属性时,如果自己没有对应的属性就回去父类上找,通过原型链一步步向上查找,直至null

var Foo = function () {this.name = "long";this.age = "10";
}
Foo.afert = function () {console.log(1);}
var foo = new Foo();
foo.__proto__ === Foo.prototype
//true
Foo.__proto__ === Function.prototype
//truefoo.toString();//有toString方法,因为Function 有。
foo.name;//用为其父类有
//"long"
foo.prototype
//undefined
foo.prototype = {ele: "element", clazz: "class"}
//Object {ele: "element", clazz: "class"}
foo.prototype.clazz
//"class"
foo.prototype.hasOwnProperty("toString")
//false
foo.prototype.hasOwnProperty("ele") //可以通过hasOwnProperty方法判断某个属性是对象自己的还重父类继承过来的
//truefoo.name
//"long"
foo.age
//"10"
foo.afert
//undefined//prototype (显式原型上的属性是可以被 子类继承的) 成员属性会被继承
//Foo.xxx  Foo构造函数静态xxx属性是不会被继承的

组件开发格式

define([], function() {/* ******组件内容****** */var Component = function() {}Component.prototype = {outFun: function() {},__innerFun: function() {}}return Component;
})

========== this 指向问题先要搞清js的 “定义”与“执行”============

this 要在执行时才能确定值,定义时无法确认("谁调指谁,没有谁调用时指window")
eg:
var a = {name: "long",fn: function () {console.log(this.name);//就是这里有bug 在定义时也无法确定}
}a.fn();// this === a
a.fn.call({name: "gong"})// this === {name: "gong"}
var fn1 = a.fn;
fn1(); // this === window//this 的指向作为构造函数执行     this.name .....
作为对象属性执行     f.callname()
作为普通函数执行     username()   this 指window
call apply bind      可以改变this的执行  call(面量对象)  apply(数组)
eg:
//执行构造函数
function Foo (name) {//this = {};this.name = name;//return this;
}
var f = new Foo('long');
f.name;//执行对象属性
var obj = {name: 'long',sex: 'man',say: function() {console.log(this.name);}
}
obj.say();// this === obj//作为普通函数执行
function testfn () {console.log(this);//this === window
}
testfn();//call apply bind
/*全局中:在执行前会确认一遍, 变量定义 函数声明.
函数中:在执行前会确认一遍,变量定义 函数声明 this argument*/
function fn1 (name) {console.log(name);console.log(this);console.log(arguments);
}
fn1.call({x:100}, 'long', '25');// this === {x:100}
fn1();function fn11 (name) {console.log(name);console.log(this);console.log(arguments);
};
fn11.apply({x:100}, ['long', '25']);// this === {x:100}
fn11();function fn2 (name) {console.log(name);console.log(this);
}
fn2("long");// this === windowfunction fn3 (name) {console.log(name);console.log(this);
}.bind({y: 200});// bind 就是用来改变this指向的
fn3("long");//【.bind 必须是函数表达式  如果是函数表达式会报错】var fn4 = function (name) {console.log(name);console.log(this);
}.bind({y: 200});// bind 就是用来改变this指向的
fn4("long");// this === {y: 200}//分清 函数定义 和 函数执行
注意:像第三方库 一般第三方库都使用call来改变 this 的指向。
.bind 必须是函数表达式  如果是函数表达式会报错

作用域与作用域链及闭包

JavaScript作用域

  1. 无块级作用域
  2. 只有函数和全局作用域
作用域
无块级作用域
只有函数和全局作用域//无块级作用域
if (true) {var name = 'long';
}
console.log(name);
在高级语言如java 中就会报错。因为 var name = "long";是块级作用域,超出块级作用域范围的console.log(name);会报错而在JavaScript中等同与下面这样(推荐使用)
var name;//先定义
if (true) {name = "long";
}
console.log(name);//函数作用域
var a = 10000;
function fn() {var a = 1000;console.log('fn', a);
}
console.log("global", a);
fn();作用域链
eg:
var a = 10000;
function fn () {var b = 1000;function fn1 () {var c = 100;function fn2 () {var d = 10;console.log(d);//10console.log(c);//100   自由变量console.log(b);//1000  自由变量console.log(a);//10000 自由变量}d = 20000;fn2();console.log("1  "+d);}fn1();console.log("2  "+d);
}
fn();下面两个例子需要好好思考
//dome1
var a = 10000;
function fn () {var b = 1000;function fn1 () {var c = 100;function fn2 () {var d = 10;console.log(d);//10console.log(c);//100   自由变量console.log(b);//1000  自由变量console.log(a);//10000 自由变量}fn2();console.log("1  "+d);d = 20000;}fn1();  d = 30000;console.log("2  "+d);
}
fn();10
100
1000
10000
1  20000  //  ????  涉及到没有var 定义的变量处理情况。
2  30000//dome2
var a = 10000;
function fn () {var b = 1000;function fn1 () {var c = 100;function fn2 () {var d = 10;console.log(d);//10console.log(c);//100   自由变量console.log(b);//1000  自由变量console.log(a);//10000 自由变量}fn2();console.log("1  "+d);d = 20000;}d = 30000;fn1();console.log("2  "+d);
}
fn();10
100
1000
10000
1  30000  //函数fn2 里面的值受影响 ????
2  20000  //函数fn2 里面的值影响 函数fn1 里面的值 ??? //demo3
var a = 100;
function fn() {var b = 200;console.log(a);//自由变量(没有找到就去"父级作用域"找)console.log(b);
}
var b = 20000;
fn ();
注意 函数外的变量一定不会影响函数里面的变量//demo4
var a = 100;
function fn() {var b = 200;console.log(a);console.log(b);
}
b = 20000;
fn ();//当前作用域没有定义的变量,即"自由变量"
定义   执行闭包
function Fn () {var a = 100;//返回一个函数 (函数作为返回值)return function () {// 一个函数的父级作用域是其定义时的作用域 不是 执行时的作用域console.log(a);//a自由变量,父作用域寻找。  (a此时形成了闭包) (那个作用域定义了他就去那个作用找,一直往上查找)}
}
// fn 得到一个函数
var fn = Fn();
var a = 200;//这个a与Fn函数里面的a是两码事
fn();//100 // 一个函数的父级作用域是其定义时的作用域 不是 执行时的作用域。如果是看函数fn执行时的作用域那fn()==>200,显然不是,所以只有是看函数fn定义时的作用域那fn() ==> 100 才是正确的//new 才会动用到构造函数里面的this
function Fn () {this.name = "123";var a = 100;//返回一个函数 (函数作为返回值)
}
// fn 得到一个函数
var fn = new Fn();
var a = 200;
fn.name;//123闭包的使用场景
1 函数作为返回值
2 函数作为参数传递function Fn () {var a = 100;return function () {console.log(a);}
}var fn = Fn();
var a = 200;
fn();//100function Fn () {var a = 100;return function () {console.log(a);// a 自由变量,父作用域寻找。父作用域是在其声明定义时的作用域,而不是其执行的作用域。本demo中的执行作用域是Fn1的作用域}
}
function Fn1 (fn) {var a = 200;fn();
}var fn1 = Fn();
Fn1(fn1);说一下对变量提升的理解是执行上下文的概念,变量定义和函数声明(注意和函数表达式的区别) 都会在执行之前全局作用域  执行前会先确定  变量定义 和 函数声明函数作用域  执行前会先确定  变量定义 和 函数声明 this arguments创建10个<a>标签 点击的时候弹出来对应的序号
//下面的是错误的,十个alert出来的都是9var i, a;for (i = 0; i < 10; i++) {a = document.createElement('a');a.innerHTML = i + '<br/>';a.addEventListener('click', function (e) {e.preventDefault();alert(i);//i 是自由变量 需要从父级作用域找寻i,但是此时i早就变成了10 (本父级作用域 是全局作用域)})document.body.appendChild(a)}var i, a;for (i = 0; i < 10; i++) {//自执行函数,就是不用调用,只要定义完成,立即执行的函数(function (i) {//i 函数作用域 定了就不受外面的影响了a = document.createElement('a');a.innerHTML = i + '<br/>';a.addEventListener('click', function (e) {e.preventDefault();alert(i);//i 是函数作用的, 需要从父级作用域中寻找 (本父级作用域 是函数作用域);被使用的变量 内存回收机制是不会回收的})document.body.appendChild(a)})(i)//形成10个函数}//下面两个只是改变this的指向又不能形成闭包var i, a;for (i = 0; i < 10; i++) {function fna () {a = document.createElement('a');a.innerHTML = i + '<br/>';a.addEventListener('click', function (e) {e.preventDefault();alert(i);});document.body.appendChild(a)}fna.bind({i: i});fna();}var i, a;for (i = 0; i < 10; i++) {function fna () {a = document.createElement('a');a.innerHTML = i + '<br/>';a.addEventListener('click', function (e) {e.preventDefault();alert(i);});document.body.appendChild(a)}fna.call({i: i});}如何理解作用域链自由变量作用域链,即自由变量的查找闭包的两个两个场景(函数作为返回值,函数作为参数传入)实际开发中闭包的应用// 闭包实际应用中主要用于封装变量,收敛权限function isFirstLoad() {var _list = [];return function (id) {if (_list.indexOf(id) >= 0) {return false;} else {_list.push(id);return true;}}}//使用var firstLoad = isFirstLoad();firstLoad(10);//truefirstLoad(10);//falsefirstLoad(20);//true//在isFirstLoad 函数外面,根本不可能修改 _list的值

单线程与异步

1 单线线程是对多线程的,对于多线程的开发语言,有一个请求就可以开一个线程处理。那,对于单线程语言,只有通过异步调用程序。【事件 (事件循环机制), 回调】

2 异步是对同步说的, 最大区别就是同步需要等待,异步这不需要等待。

【异步】非阻塞(function funyb () {console.log(1);setTimeout(function () {console.log(2)}, 3000);console.log(3);})()//1//3//2注意: setTimeout(fun,ms);
//fun 是一个函数。 比如 function(){console.log(2)}
//fun 不能是一个函数执行。 比如 console.log(2) 这样setTimeout的 ms数就没有用了。而是立即执行【同步】会阻塞
(function funyb () {console.log(1);alert(2);//这个执行完才会往下。alert 不点击确定就一直不执行console.log(3)console.log(3);})()

会采用异步的三种情况 可以写3个例子分别看看

  1. 在定时执行时, 如:setTimeout,setInterval
  2. 请求数据和图片、音频、视频资源时,如 ajax 、img 、audio、video … 这些资源都要很长的等待时间
  3. 事件,因为事件只是在用户点击的时候才会触发

!!!需要等待 就异步
!!!需要等待 就异步
!!!需要等待 就异步

注意:闭包容易出现内存泄漏,就是内存空间无法被gc回收。

//10个a标签
Array.prototype.slice.call(document.querySelectorAll("a")).forEach(function (item, index) {//在内存中形成10 closest 函数。会占用内存。只是i的值不同0 -> 9function closest (i) {//代码.....}.bind({i: index}) //父类还没用完 就不能清除//这两个是一样的//(function closest (i) {//   //代码....    //})(index)
})

经典dome

JavaScript 三座大山相关推荐

  1. JavaScript 的三座大山

    js 作为前端的中坚力量.那么 javascript 三座大山,你知道是哪些呢? 1️⃣ 作用域和闭包 作用域 指代码当前上下文,控制着变量和函数的可见性和生命周期.最大的作用是隔离变量,不同作用域下 ...

  2. aurelia中文开发手记(一):写在前面

    5月中旬开始学习前端,从大神处获得一套有如神助的框架叫aurelia(奥瑞利亚).学习笔记开始. 以前我开发桌面小应用开始,使用了visual studio,不得不说,这个软件确实集成度高的令人发指, ...

  3. web前端面试高频考点——JavaScript 篇(一)【JS的三座大山 】 原型和原型链、作用域和闭包、异步

    系列文章目录 JavaScript 知识梳理,收录了web前端面试 95%以上 的高频考点,满满的干货.给你做一个高效的知识梳理,为你的面试保驾护航! 内容 参考链接 HTML & CSS 篇 ...

  4. 前端javascript总结笔记(一)--js的三座大山

    前言: 第一章为变量类型和计算. 第二章到第四章分别是原型与原型链,作用域及闭包,异步和单线程,这三个就是我们说的三座大山. 一.变量类型和计算 1:JS中使用typeof能得到哪些类型? 字符串(S ...

  5. javascript基础知识之三座大山

    三座大山:1.原型  原型链 2.作用域  闭包 3.异步  单线程 一.原型  原型链 知识点: (1)构造函数 (2)构造函数扩展 (3)原型规则和示例 二.作用域  闭包 知识点: (1)执行上 ...

  6. JavaScript的三座大山

    前言:这个题目是抄的,看着很有意思,就拿过用了,毕竟CV是程序员的基本功底嘛,顺带把图也拿过来了 作用域和闭包 这个几乎是天天在用的东西,可能有些人甚至不知道这个概念,但是用到过这种方法去解决某一些问 ...

  7. JavaScript异步(必考三座大山之三)——第四集:async-await

    前言 现在使用JavaScript开发的异步编程,基本上被async-await承包了,所以这个东西你不能不会. 第三集我们讲解到,要想解决异步的回调地狱,可以使用Promise对象里面内置的方法th ...

  8. JavaScript的三座大山--(2)--作用域和闭包

    文章可能有点长,但 

  9. JavaScript的三座大山--(3)--单线程和异步

    就差最后一步啦,冲鸭

最新文章

  1. C++STL容器vector
  2. Acdream Path 动态规划
  3. 一文读懂 Spring的前世今生
  4. Elasticsearch from、scroll、search_after 分页查询对比
  5. Linux Centos6.5如何截图
  6. StakeDAO新增Sushiswap流动性奖励计划
  7. python:threading多线程模块-使用Queue模块保持线程同步
  8. 在IT界取得成功应该知道的10件事(ZT)
  9. Postfix+Dovecot+LAMP+Extmail搭建web邮件系统(二)
  10. 【历史上的今天】8 月 29 日:Wolfram 语言之父、“新”科学家 Stephen Wolfram 的诞生
  11. python 循环语句s =2+22+222+2222之和_python算法题
  12. 希尔密码_希尔密码| 网络安全
  13. 虚拟化安全防护系统部署在安全服务器上,虚拟化安全及解决方案
  14. VMware16阿里云盘
  15. 2020 年的风口是什么?
  16. Phonetic symbol 辅音 - 清辅音/ -- /h/
  17. 还在抠图?百万张PNG透明图片免费下载!
  18. 163邮箱会员揭秘,163邮箱注册,你最想了解的几件事
  19. JavaScript中的appendChild()方法
  20. 华中科技大计算机考研相关信息

热门文章

  1. 做IT项目经理什么要求?
  2. Linux 命令(142)—— hexdump 命令
  3. XtraReport数据绑定模式比较
  4. 复习单片机:点亮LED(内含实物图+硬件设计+软件编程+原始代码)
  5. 短代码 html,WooCommerce 默认提供的简码短代码
  6. VMware虚拟机中安装的Linux系统无法识别U盘解决方法
  7. HashMap方法tableSizeFor解析
  8. ABP框架Web API跨域问题的解决方案
  9. 《数字图像处理》-(3)-1从傅里叶级数到傅里叶变换详细推导以及傅里叶图像的性质
  10. 每日一题 | 数学神童的红眼睛与蓝眼睛问题