IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JavaScript(8) 闭包-原型 -> 正文阅读

[JavaScript知识库]JavaScript(8) 闭包-原型

一、作用域

作用域是可访问变量的有效范围。

  • 全局作用域

作用于所有代码执行的环境 (整个script标签内部) 或独立的js文件。

  • 局部作用域(函数作用域)

作用于函数内的代码环境,就是局部作用域。

  • 全局变量

在全局作用域下(函数外部)声明的变量叫做全局变量。

  1. 网页中所有脚本和函数均可使用全局变量
  2. 如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量(不建议使用)
var global = '全局变量';  // global变量就是全局变量
function test1() {
  var name = 'zhangsan';  // name变量是局部变量
  console.log(global);  // 返回:全局变量;函数内部可以访问全局变量global
  console.log(name); // 返回:zhangsan;函数内部可以访问本函数内的局部变量name
}
test1();

//如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
function test3() {
  age = '未声明的变量';
  console.log(age);  // 返回:未声明的变量;age变量未声明直接使用,则该变量是全局变量,函数内部可调用age变量
}
test3();
console.log(age); // 返回:未声明的变量;函数外部也可以调用age变量
  • 局部变量

在局部作用域下(函数内部)声明的变量叫做局部变量。

  1. 局部变量只能在该函数内部使用。
  2. 局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。
  3. 因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。
  4. 函数参数只在函数内起作用,是局部变量。
function test2() {
  var name = 'lisi';
  console.log(name); // 返回:lisi; 不同函数可以声明相同的变量而不受影响
}
test2();
  • 全局变量和局部变量的区别
  1. 全局变量: 网页中所有脚本和函数均可使用,只有在浏览器关闭时才会被销毁,因此比较占内存
  2. 局部变量: 只在函数内部使用,当其所在的代码块被执行时,会被初始化,当代码块运行结束后,就会被销毁,因此更节省内存空间
  • 全局变量/函数,可以覆盖window对象的变量/函数。
// 全局变量/函数,可以覆盖window对象的变量/函数。
window.variable = 'window对象的变量';
var variable = '全局变量';
console.log(variable); // 返回:全局变量
  • 局部变量/函数,可以覆盖window对象的变量和全局变量/window对象的函数和全局变量的函数。
// 局部变量/函数,可以覆盖window对象的变量和全局变量/window对象的函数和全局变量的函数。
function test4() {
  var variable = '局部变量';
  console.log(variable); // 返回:局部变量
}
test4();

二、闭包

函数函数内部能访问到的变量 的总和,就是一个闭包。

function fn1() {
  var num = 10;
  function fn2() {
    return num;
  }
  return fn2;  // fn2没有调用不执行,fn1的返回值是fn2函数
}
var f = fn1(); // 调用fn1,得到返回值--fn2函数,把它保存到变量f中
f();  // 此时f保存的是fn2函数,调用该函数,就能得到fn2的返回值--num
console.log(f());  // 10
function test1() {
  var local = "变量"; //局部变量
  function foo() {
    return local;
  }
  return foo;
}

function test2() {
  //调用test1函数,得到foo函数,被t1接收
  var t1 = test1();
  //调用t1就是就是访问foo函数
  var val = t1();
  alert(val);
}
test2();

闭包的作用:

闭包常常用来 间接访问一个变量。换句话说,隐藏一个变量修改权利

错误的认识:

  1. 闭包不是函数套函数

    是因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的——隐藏变量

  2. 闭包中的函数是可以没有return语句

    因为如果不 return,你就无法使用这个闭包。把 return foo 改成 window.foo = foo 也是一样的,只要让外面可以访问到这个 foo 函数就行了。

    所以 return foo 只是为了 foo 能被使用,也跟闭包无关。

三、原型

var arr1 = [1, 0, 0, 8, 6];
var arr2 = [1, 0, 0, 8, 6, 1, 1];

// arr1升序排序
arr1.sort(function (a, b) {
  return a - b;
});
// arr2升序排序
arr2.sort(function (a, b) {
  return a - b;
});

console.log(arr1);  // [0, 0, 1, 6, 8]
console.log(arr2);  // [0, 0, 1, 1, 1, 6, 8]

console.log(arr1 === arr2);  // false 因为arr1和arr2中的元素和元素个数不同。
console.log(arr1.sort === arr2.sort);  //true 因为arr1和arr2使用的是相同的sort方法,sort方法是arr1和arr2的公共方法

JavaScript是如何做到让sort方法是arr1和arr2的公共方法?

arr1.getSum = function () {
  var sum = 0;
  for (var i = 0; i < this.length; i++) {
    sum += this[i];
  }
  return sum;
}
var a = arr1.getSum();
console.log(a);  // 15

var b = arr2.getSum();
console.log(b);  // 报错:arr2.getSum is not a function 因为arr2没有getSum()方法

那么有没有解决方案,函数只定义一次,然后提供给不同的变量使用呢?

答案是有的:将getSum定义为原型方法

Array.prototype.getSum = function () {
  var sum = 0;
  for (var i = 0; i < this.length; i++) {
    sum += this[i];
  }
  return sum;
}
console.log(arr1.getSum());  // 15
console.log(arr2.getSum());  // 17

Array.prototype.getSum = function(){}将getSum()方法给了Array.prototype,此时getSum()方法就成了原型方法,由此可知Array.prototype是数组的原型对象。

得到的结果是对象arr1和arr2就可以共享getSum方法了。

下面以构造函数方式创建对象,把不变的方法直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
}
Star.prototype.sing = function () {
  console.log('我会唱歌');
}
var ldh = new Star('刘德华', 20);
var zxy = new Star('张学友', 25);
ldh.sing();  // 我会唱歌  ldh实例调用构造函数原型的方法
zxy.sing();  // 我会唱歌  zxy实例调用构造函数原型的方法

构造函数通过原型分配的函数是所有对象所共享的。

JavaScript 规定,每一个构造函数都有一个**prototype 属性**,指向另一个对象。

注意:这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

对象都会有一个属性 __proto__ ,指向构造函数的 prototype 原型对象。

之所以对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__原型 的存在。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 10:46:10  更:2021-09-10 10:46:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:57:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码