// 代码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的对象属性
- 每个对象都有一个 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 个评论
要回复文章请先登录或注册