纯牛奶645
纯牛奶645
  • 发布:2018-06-24 09:38
  • 更新:2018-06-24 09:38
  • 阅读:1497

闭包 作用域 原型链

分类:Native.js
js
// 代码1  
if(!("userName" in window)) {  
  var userName = "yang"  
}  
console.log(userName) // undefined  
if是一个块,在ES6里有块级作用域,在ES5里是没有这个概念的。  
// 代码2  
var obj = {  
  user: "yang",  
  getName: function () {  
    return this.user;  
  }  
}  
var getNameFn = obj.getName;  
console.log(getNameFn()) // Uncaught ReferenceError: user is not defined  
console.log(obj.getName()) // Uncaught ReferenceError: user is not defined  

var obj = {  
  user: "yang",  
  getName: function () {  
    return this.user;  
  }  
}  
var getNameFn = obj.getName;  
console.log(getNameFn()) // Uncaught ReferenceError: user is not defined  
console.log(obj.getName()) // "yang"  

作用域
1、程序级
2、文件级
3、函数级
4、块级

全局作用域、函数作用域、块级作用域(es6)
js中只有一个局部作用域就是函数作用域

// 代码3  
var global  = 1;  
function doSomething() {  
  var inner = 2;  
 globalA = 3;  
}  
doSomething();  
alert(global);  // 1  
alert(globalA); // 3  
alert(inner);  // undefined

什么是作用域链?
在js中,函数也是对象,函数对象和其他对象一样,拥有可以通过代码访问的属性和一系列仅供js引擎访问的内部函数,其中一个内部属性是【scope】,由ECMA-262标准第三版定义,该内部属性包含了函数被创建作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

var x = 1;  
function foo () {  
  var y = 1 + x;  
  return function () {  
    var z = 1 + y;  
    return z;  
  }  
}  
foo()();  

// 代码4  
var test = "aa"  
function doSomething() {  
  alert(test) // undefined 变量与函数的声明提前,永远访问不到外部的test  
  var test = "bb"  
  alert(test) // bb  
}  
doSomething()  
alert(test) //aa  

**变量与函数的声明提前**  

function foo () {  
  alert(test);  
  var test = "bb"  
  alert(test)  
}  
foo()  
执行顺序:  
1.声明函数foo  
2. 调用函数foo  
3. 声明变量test  
4. alert(test)  
5.test变量赋值为bb  
6.alert(test)  

js中this关键字
this指向哪里?
在js中,this指向函数执行时的当前对象。
this的使用场景
》普通函数中:
严格模式中:undefined
非严格模式中:全局对象(window)
》构造函数中:对象的实例
》对象方法:对象本身
call、apply、bind
通过这三个方法可以改变被调用函数中this指向的对象

原型对象是什么
在js中,每定义一个对象(函数)时,对象中都会包含一些预定义的属性。其中函数对象的一个属性就是原型对象prototype。普通对象没有prototype属性,但有proto属性

function f1() {};  
console.log(typeof f1.prototype) // Object  
console.log(typeof Function.prototype) // Function,这个特殊  
console.log(typeof Object.prototype) // Object  
console.log(typeof Function.prototype.prototype) //undefined

原型对象有什么用?
面向对象开发、类的继承

function Person(name) {  
  this.name = name;  
}  
Person.prototype.getName = function () {  
  return this.name;  
}  
var sub = new Person("yang")  
sub.getName() //yang

构造函数
使用new关键字调用一个函数的时候,这个函数就叫构造函数
构造函数可以实例化一个对象
返回值,默认返回类的实例
特殊情况:没有返回值、简单数据类型、对象类型
原型链
1.每个函数都有一个prototype的对象属性

  1. 每个对象都有一个 proto 属性,该属性指向其父类的prototype对象
    原型对象中的constructor
    每个原型对象prototype中都有一个constructor属性,默认指向函数本身
    
    // test 1  
    function make(num) {  
    return function () {  
    return num;  
    }  
    }  

var arr = [make(0),make(1),make(2)]
alert(arr[0]()) // 0
alert(arr[1]()) // 1
alert(arr[2]()) // 2

// test 2
var name = "global"
function A(name) {
// 参数name就是一个变量声明
alert(name) // 3
this.name = name
var name = "1" // 这个name完全不影响
}
A.prototype.name = "2" // 在原型链上后调用
var a = new A("3")
alert(a.name) // 3
delete a.name
alert(a.name) // 2

// test 3
function fun (n,o) {
console.log(o)
return {
fun: function(m) {
return fun(m,n) //访问的是最外层的fun,如果要访问return里的fun,一定是XXX.fun(),一定有“.”这个点
}
}
}
var a = fun(0) // undefined
a.fun(1) // 一定是通过这种方法才能访问到对象的fun,而函数fun不同
a.fun(2)
var b = fun(0).fun(1).fun(2).fun(3)
var c = fun(0).fun(1)
c.fun(2)
c.fun(3)
相关说明:https://segmentfault.com/a/1190000004187681
其实是这样的
function _fun (n,o) {
console.log(o)
return {
fun: function(m) {
return _fun(m,n) //访问的是最外层的fun,如果要访问return里的fun,一定是XXX.fun(),一定有“.”这个点
}
}
}


chrome调试作用域链  
闭包就是一个函数一个作用域,使用场景  
使用的i函数就是一个局部作用域,就是一个闭包  
闭包会引起内存泄漏为什么还要用它?  
涉及到js的垃圾回收,循环引用,会在闭包执行完之后进行回收,内存泄漏是认为写代码不当导致的,函数式编程中闭包更常用。  

变量的提前声明  
《函数式编程》  
lodash  
0 关注 分享

要回复文章请先登录注册