js之柯里化与反柯里化

先给大家介绍什么是柯里化与反柯里化

百度翻译:

  • 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
  • 柯里化
    • 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果。因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程。
    • 另一方面可以说柯里化是将一个通用性很高的函数变成高是实用性的函数,高通用性的函数必定适用性相对就低了。
    • 比如:你制定了x和y, 如2的3次方,就返回8, 如果你只制定x为2,y没指定, 那么就返回一个函数:2的y次方, 这个函数只有一个参数:y。这样就非常容易理解吧。
  • 反柯里化
    • 反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.
  • 特点
    • 提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性。 对于一个已有函数,对其约定好其中的某些参数输入,然后生成一个更有好的、更符合业务逻辑的函数。

掌握JavaScript函数的柯里化

Haskellscala都支持函数的柯里化,JavaScript函数的柯里化还与JavaScript的函数编程有很大的联系,如果你感兴趣的话,可以在这些方面多下功夫了解,相信收获一定很多.

??看本篇文章需要知道的一些知识点

  • 函数部分的call/apply/arguments
  • 闭包
  • 高阶函数
  • 不完全函数

文章后面有对这些知识的简单解释,大家可以看看.

??什么是柯里化?

我们先来看看维基百科中是如何定义的:在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

我们可以举个简单的例子,如下函数add是一般的一个函数,就是将传进来的参数a和b相加;函数curryingAdd就是对函数add进行柯里化的函数; 这样一来,原来我们需要直接传进去两个参数来进行运算的函数,现在需要分别传入参数a和b,函数如下:

看到这里你可能会想,这样做有什么用?为什么要这样做?这样做能够给我们的应用带来什么样的好处?先别着急,我们接着往下看.

function add(a, b) {
return a + b;
}

function curryingAdd(a) {
return function(b) {
return a + b;
}
}

add(1, 2); // 3curryingAdd(1)(2); // 3

??为什么要对函数进行柯里化?

  • ??可以使用一些小技巧(见下文)
  • ??提前绑定好函数里面的某些参数,达到参数复用的效果,提高了适用性.
  • ??固定易变因素
  • ??延迟计算

总之,函数的柯里化能够让你重新组合你的应用,把你的复杂功能拆分成一个一个的小部分,每一个小的部分都是简单的,便于理解的,而且是容易测试的;

??如何对函数进行柯里化?

在这一部分里,我们由浅入深的一步步来告诉大家如何对一个多参数的函数进行柯里化.其中用到的知识有闭包,高阶函数,不完全函数等等.

  • I 开胃菜

    假如我们要实现一个功能,就是输出语句name喜欢song,其中name和song都是可变参数;那么一般情况下我们会这样写:

    function printInfo(name, song) {
    console.log(name + ‘喜欢的歌曲是: ‘ + song);
    }
    printInfo(‘Tom‘, ‘七里香‘);
    printInfo(‘Jerry‘, ‘雅俗共赏‘);
    
    对上面的函数进行柯里化之后,我们可以这样写:
    function curryingPrintInfo(name) {
    return function(song) {
    console.log(name + ‘喜欢的歌曲是: ‘ + song);
    }
    }
    var tomLike = curryingPrintInfo(‘Tom‘);
    tomLike(‘七里香‘);
    var jerryLike = curryingPrintInfo(‘Jerry‘);
    jerryLike(‘雅俗共赏‘);
  • II 小鸡炖蘑菇

    上面我们虽然对对函数printInfo进行了柯里化,但是我们可不想在需要柯里化的时候,都像上面那样不断地进行函数的嵌套,那简直是噩梦; 所以我们要创造一些帮助其它函数进行柯里化的函数,我们暂且叫它为curryingHelper吧,一个简单的curryingHelper函数如下所示:

    function curryingHelper(fn) {
    var _args = Array.prototype.slice.call(arguments, 1);
    return function() {
    var _newArgs = Array.prototype.slice.call(arguments);
    var _totalArgs = _args.concat(_newArgs);
    return fn.apply(this, _totalArgs);
    }
    }

    这里解释一点东西,首先函数的arguments表示的是传递到函数中的参数对象,它不是一个数组,它是一个类数组对象; 所以我们可以使用函数的Array.prototype.slice方法,然后使用.call方法来获取arguments里面的内容. 我们使用fn.apply(this, _totalArgs)来给函数fn传递正确的参数.

    接下来我们来写一个简单的函数验证上面的辅助柯里化函数的正确性, 代码部分如下:

    function showMsg(name, age, fruit) {
    console.log(‘My name is ‘ + name + ‘, I\‘m ‘ + age + ‘ years old, ‘ + ‘ and I like eat ‘ + fruit);
    }
    
    var curryingShowMsg1 = curryingHelper(showMsg, ‘dreamapple‘);
    curryingShowMsg1(22, ‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat apple
    
    var curryingShowMsg2 = curryingHelper(showMsg, ‘dreamapple‘, 20);
    curryingShowMsg2(‘watermelon‘); // My name is dreamapple, I‘m 20 years old, and I like eat watermelon

    上面的结果表示,我们的这个柯里化的函数是正确的.上面的curryingHelper就是一个高阶函数,关于高阶函数的解释可以参照下文.

  • III 牛肉火锅

    上面的柯里化帮助函数确实已经能够达到我们的一般性需求了,但是它还不够好,我们希望那些经过柯里化后的函数可以每次只传递进去一个参数, 然后可以进行多次参数的传递,那么应该怎么办呢?我们可以再花费一些脑筋,写出一个betterCurryingHelper函数,实现我们上面说的那些 功能.代码如下:

    function betterCurryingHelper(fn, len) {
    var length = len || fn.length;
    return function () {
    var allArgsFulfilled = (arguments.length >= length);
    
    // 如果参数全部满足,就可以终止递归调用
    if (allArgsFulfilled) {
    return fn.apply(this, arguments);
    }
    else {
    var argsNeedFulfilled = [fn].concat(Array.prototype.slice.call(arguments));
    return betterCurryingHelper(curryingHelper.apply(this, argsNeedFulfilled), length - arguments.length);
    }
    };
    }

    其中curryingHelper就是上面II 小鸡炖蘑菇中提及的那个函数.需要注意的是fn.length表示的是这个函数的参数长度. 接下来我们来检验一下这个函数的正确性:

    var betterShowMsg = betterCurryingHelper(showMsg);
    betterShowMsg(‘dreamapple‘, 22, ‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applebetterShowMsg(‘dreamapple‘, 22)(‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applebetterShowMsg(‘dreamapple‘)(22, ‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applebetterShowMsg(‘dreamapple‘)(22)(‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat apple

    其中showMsg就是II 小鸡炖蘑菇部分提及的那个函数. 我们可以看出来,这个betterCurryingHelper确实实现了我们想要的那个功能.并且我们也可以像使用原来的那个函数一样使用柯里化后的函数.

  • IV 泡椒凤爪

    我们已经能够写出很好的柯里化辅助函数了,但是这还不算是最刺激的,如果我们在传递参数的时候可以不按照顺来那一定很酷;当然我们也可以写出这样的函数来, 这个crazyCurryingHelper函数如下所示:

    var _ = {};
    function crazyCurryingHelper(fn, length, args, holes) {
    length = length || fn.length;
    args = args || [];
    holes = holes || [];
    
    return function() {
    var _args = args.slice(),
    _holes = holes.slice();
    
    // 存储接收到的args和holes的长度
    var argLength = _args.length,
    holeLength = _holes.length;
    
    var allArgumentsSpecified = false;
    
    // 循环
    var arg = null,
    i = 0,
    aLength = arguments.length;
    
    for(; i < aLength; i++) {
    arg = arguments[i];
    
    if(arg === _ && holeLength) {
    // 循环holes的位置
    holeLength--;
    _holes.push(_holes.shift());
    } else if (arg === _) {
    // 存储hole就是_的位置
    _holes.push(argLength + i);
    } else if (holeLength) {
    // 是否还有没有填补的hole
    // 在参数列表指定hole的地方插入当前参数
    holeLength--;
    _args.splice(_holes.shift(), 0, arg);
    } else {
    // 不需要填补hole,直接添加到参数列表里面
    _args.push(arg);
    }
    }
    
    // 判断是否所有的参数都已满足
    allArgumentsSpecified = (_args.length >= length);
    if(allArgumentsSpecified) {
    return fn.apply(this, _args);
    }
    
    // 递归的进行柯里化
    return crazyCurryingHelper.call(this, fn, length, _args, _holes);
    };
    }

    一些解释,我们使用_来表示参数中的那些缺失的参数,如果你使用了lodash的话,会有冲突的;那么你可以使用别的符号替代. 按照一贯的尿性,我们还是要验证一下这个crazyCurryingHelper是不是实现了我们所说的哪些功能,代码如下:

    var crazyShowMsg = crazyCurryingHelper(showMsg);
    crazyShowMsg(_, 22)(‘dreamapple‘)(‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applecrazyShowMsg( _, 22, ‘apple‘)(‘dreamapple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applecrazyShowMsg( _, 22, _)(‘dreamapple‘, _, ‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applecrazyShowMsg( ‘dreamapple‘, _, _)(22)(‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat applecrazyShowMsg(‘dreamapple‘)(22)(‘apple‘); // My name is dreamapple, I‘m 22 years old, and I like eat apple

    结果显示,我们这个函数也实现了我们所说的那些功能.

??柯里化的一些应用场景

说了那么多,其实这部分才是最重要的部分;学习某个知识要一定可以用得到,不然学习它干嘛??

  • 关于函数柯里化的一些小技巧
    • 给setTimeout传递地进来的函数添加参数

      一般情况下,我们如果想给一个setTimeout传递进来的函数添加参数的话,一般会使用这种方法:

      function hello(name) {
      console.log(‘Hello, ‘ + name);
      }
      setTimeout(hello(‘dreamapple‘), 3600); //立即执行,不会在3.6s后执行setTimeout(function() {
      hello(‘dreamapple‘);
      }, 3600); // 3.6s 后执行

      我们使用了一个新的匿名函数包裹我们要执行的函数,然后在函数体里面给那个函数传递参数值.

      当然,在ES5里面,我们也可以使用函数的bind方法,如下所示:

      setTimeout(hello.bind(this, ‘dreamapple‘), 3600); // 3.6s 之后执行函数

      这样也是非常的方便快捷,并且可以绑定函数执行的上下文.

      我们本篇文章是讨论函数的柯里化,当然我们这里也可以使用函数的柯里化来达到这个效果:

      setTimeout(curryingHelper(hello, ‘dreamapple‘), 3600); // 其中curryingHelper是上面已经提及过的

      这样也是可以的,是不是很酷.其实函数的bind方法也是使用函数的柯里化来完成的,详情可以看这里Function.prototype.bind().

    • 写出这样一个函数multiply(1)(2)(3) == 6结果为true,multiply(1)(2)(3)(...)(n) == (1)*(2)*(3)*(...)*(n)结果为true

      这个题目不知道大家碰到过没有,不过通过函数的柯里化,也是有办法解决的,看下面的代码:

      function multiply(x) {
      var y = function(x) {
      return multiply(x * y);
      };
      y.toString = y.valueOf = function() {
      return x;
      };
      return y;
      }
      
      console.log(multiply(1)(2)(3) == 6); // trueconsole.log(multiply(1)(2)(3)(4)(5) == 120); // true

      因为multiply(1)(2)(3)的直接结果并不是6,而是一个函数对象{ [Number: 6] valueOf: [Function], toString: [Function] },我们 之后使用了==会将左边这个函数对象转换成为一个数字,所以就达到了我们想要的结果.还有关于为什么使用toString和valueOf方法 可以看看这里的解释Number.prototype.valueOf(),Function.prototype.toString().

    • 上面的那个函数不够纯粹,我们也可以实现一个更纯粹的函数,但是可以会不太符合题目的要求. 我们可以这样做,先把函数的参数存储,然后再对这些参数做处理,一旦有了这个思路,我们就不难写出些面的代码:
      function add() {
      var args = Array.prototype.slice.call(arguments);
      var _that = this;
      return function() {
      var newArgs = Array.prototype.slice.call(arguments);
      var total = args.concat(newArgs);
      if(!arguments.length) {
      var result = 1;
      for(var i = 0; i < total.length; i++) {
      result *= total[i];
      }
      return result;
      }
      else {
      return add.apply(_that, total);
      }
      }
      }
      add(1)(2)(3)(); // 6add(1, 2, 3)(); // 6
    • 当我们的需要兼容IE9之前版本的IE浏览器的话,我们可能需要写出一些兼容的方案 ,比如事件监听;一般情况下我们应该会这样写:
      var addEvent = function (el, type, fn, capture) {
      if (window.addEventListener) {
      el.addEventListener(type, fn, capture);
      }
      else {
      el.attachEvent(‘on‘ + type, fn);
      }
      };

      这也写也是可以的,但是性能上会差一点,因为如果是在低版本的IE浏览器上每一次都会运行if()语句,产生了不必要的性能开销. 我们也可以这样写:

      var addEvent = (function () {
      if (window.addEventListener) {
      return function (el, type, fn, capture) {
      el.addEventListener(type, fn, capture);
      }
      }
      else {
      return function (el, type, fn) {
      var IEtype = ‘on‘ + type;
      el.attachEvent(IEtype, fn);
      }
      }
      })();

      这样就减少了不必要的开支,整个函数运行一次就可以了.

  • 延迟计算

    上面的那两个函数multiply()和add()实际上就是延迟计算的例子.

  • 提前绑定好函数里面的某些参数,达到参数复用的效果,提高了适用性.

    我们的I 开胃菜部分的tomLike和jerryLike其实就是属于这种的,绑定好函数里面的第一个参数,然后后面根据情况分别使用不同的函数.

  • 固定易变因素

    我们经常使用的函数的bind方法就是一个固定易变因素的很好的例子.

??关于柯里化的性能

当然,使用柯里化意味着有一些额外的开销;这些开销一般涉及到这些方面,首先是关于函数参数的调用,操作arguments对象通常会比操作命名的参数要慢一点; 还有,在一些老的版本的浏览器中arguments.length的实现是很慢的;直接调用函数fn要比使用fn.apply()或者fn.call()要快一点;产生大量的嵌套 作用域还有闭包会带来一些性能还有速度的降低.但是,大多数的web应用的性能瓶颈时发生在操作DOM上的,所以上面的那些开销比起DOM操作的开销还是比较小的.

??关于本章一些知识点的解释

  • 琐碎的知识点

    fn.length: 表示的是这个函数中参数的个数.

    arguments.callee: 指向的是当前运行的函数.callee是arguments对象的属性。 在该函数的函数体内,它可以指向当前正在执行的函数.当函数是匿名函数时,这是很有用的,比如没有名字的函数表达式(也被叫做"匿名函数"). 详细解释可以看这里arguments.callee.我们可以看一下下面的例子:

    function hello() {
    return function() {
    console.log(‘hello‘);
    if(!arguments.length) {
    console.log(‘from a anonymous function.‘);
    return arguments.callee;
    }
    }
    }
    
    hello()(1); // hello
    
    /* * hello * from a anonymous function. * hello * from a anonymous function. */hello()()();

    fn.caller: 返回调用指定函数的函数.详细的解释可以看这里Function.caller,下面是示例代码:

    function hello() {
    console.log(‘hello‘);
    console.log(hello.caller);
    }
    
    function callHello(fn) {
    return fn();
    }
    
    callHello(hello); // hello [Function: callHello]
  • 高阶函数(high-order function)

    高阶函数就是操作函数的函数,它接受一个或多个函数作为参数,并返回一个新的函数. 我们来看一个例子,来帮助我们理解这个概念.就举一个我们高中经常遇到的场景,如下:

    f1(x, y) = x + y;

    f2(x) = x * x;

    f3 = f2(f3(x, y));

    我们来实现f3函数,看看应该如何实现,具体的代码如下所示:

    function f1(x, y) {
    return x + y;
    }
    
    function f2(x) {
    return x * x;
    }
    
    function func3(func1, func2) {
    return function() {
    return func2.call(this, func1.apply(this, arguments));
    }
    }
    
    var f3 = func3(f1, f2);
    console.log(f3(2, 3)); // 25

    我们通过函数func3将函数f1,f2结合到了一起,然后返回了一个新的函数f3;这个函数就是我们期望的那个函数.

  • 不完全函数(partial function)

    什么是不完全函数呢?所谓的不完全函数和我们上面所说的柯里化基本差不多;所谓的不完全函数,就是给你想要运行的那个函数绑定一个固定的参数值; 然后后面的运行或者说传递参数都是在前面的基础上进行运行的.看下面的例子:

    // 一个将函数的arguments对象变成一个数组的方法function array(a, n) {
    return Array.prototype.slice.call(a, n || 0);
    }
    // 我们要运行的函数function showMsg(a, b, c){
    return a * (b - c);
    }
    
    function partialLeft(f) {
    var args = arguments;
    return function() {
    var a = array(args, 1);
    a = a.concat(array(arguments));
    console.log(a); // 打印实际传递到函数中的参数列表
    return f.apply(this, a);
    }
    }
    
    function partialRight(f) {
    var args = arguments;
    return function() {
    var a = array(arguments);
    a = a.concat(array(args, 1));
    console.log(a); // 打印实际传递到函数中的参数列表
    return f.apply(this, a);
    }
    }
    
    function partial(f) {
    var args = arguments;
    return function() {
    var a = array(args, 1);
    var i = 0; j = 0;
    for(; i < a.length; i++) {
    if(a[i] === undefined) {
    a[i] = arguments[j++];
    }
    }
    a = a.concat(array(arguments, j));
    console.log(a); // 打印实际传递到函数中的参数列表
    return f.apply(this, a);
    }
    }
    
    partialLeft(showMsg, 1)(2, 3); // 实际参数列表: [1, 2, 3] 所以结果是 1 * (2 - 3) = -1partialRight(showMsg, 1)(2, 3); // 实际参数列表: [2, 3, 1] 所以结果是 2 * (3 - 1) = 4partial(showMsg, undefined, 1)(2, 3); // 实际参数列表: [2, 1, 3] 所以结果是 2 * (1 - 3) = -4

    转载至:https://www.jianshu.com/p/f02148c64bed?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation(鸣谢)

原文地址:https://www.cnblogs.com/bgwhite/p/9407965.html

时间: 2024-10-17 17:58:00

js之柯里化与反柯里化的相关文章

JS的防抖,节流,柯里化和反柯里化

今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊.事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的 节流 首先我们来搞一下节流,啥叫节流,就是将高频率触发事件变成低频率触发事件,举个简单的例子,但我们用window.onscroll滚动事件的时候你会发现滚轮滑动一次可能会触发好多次事件, 代码: window.onscroll = function(){ console.log("触发")

柯里化与反柯里化

柯里化 什么是柯里化 柯里化(英语:Currying),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 柯里化的基础 上面的代码其实是一个高阶函数(high-order function), 高阶函数是指操作函数的函数,它接收一个或者多个函数作为参数,并返回一个新函数.此外,还依赖与闭包的特性,来保存中间过程中输入的参数.即: 函数可以作为参数传递 函数能够作为函数的返回值 闭包 通用实现 var currying

js高阶函数应用—函数柯里化和反柯里化

在Lambda演算(一套数理逻辑的形式系统,具体我也没深入研究过)中有个小技巧:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,因为高阶函数是可以当参数传递和返回值的,所以问题就简化为:写一个只有一个参数的函数,而这个函数返回一个带参数的函数,这样就实现了能写两个参数的函数了(具体参见下边代码)--这就是所谓的柯里化(Currying,以逻辑学家Hsakell Curry命名),也可以理解为一种在处理函数过程中的逻辑思维方式. 1 function add(a, b) { 2 retur

js反柯里化个人理解以及操作

学过js的都知道原型是js的灵魂,我刚接触原型的时候觉得还挺绕的,然后看了一系列的解释然后自己理了一下思路,总算是清晰了,今天我弄了一下柯里化和反柯里化,对反柯里化结合原型链有了一定的认识,一下是我所总结的. 反柯里化,个人解释就是通过添加对象或者函数的原型的方法,让原本使用范围具有局限性的一段代码能够适用范围更广,例如,数组的reduce,map,foreach这些函数都只能通过数组对象使用,如果字符串要使用其方法,必须通过call,bind,apply的方式去修改函数的调用主体,但是我们完全

JavaScript 反柯里化

浅析 JavaScript 中的 函数 uncurrying 反柯里化 柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果.因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程.请见我的另一篇博客· 浅析 JavaScript 中的 函数 currying 柯里化 反柯里化 相反,反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以

javascript之反柯里化(uncurrying)

在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点.可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原本不属于他的方法. 通常让对象去借用一个原本不属于它的方法,可以用call和apply实现,如下 更常见的场景之一是让类数组对象去借用Array.prototype的方法: (function(){ Array.prototype.push.call(arguments,4) console.log

反柯力化深度解析

柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果.因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程. 反柯里化 相反,反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.即把如下给定的函数签名, obj.func(arg1, arg2) 转化成一个函数形式,签名如下: func(obj, arg1, arg2)

扁平化2.0:扁平化设计以前从未有的6个设计风格

时至今日,扁平化已不再是流行一时的设计风潮,而是一种美学风格.扁平化大胆的用色,简洁明快的界面风格一度让大家耳目一新,当它对元素效果抛弃的如此彻底之际,它又将效果捡起来,改装成另一番模样,使得扁平化进化为扁平化2.0. 扁平化设计特质 对于扁平化的定义,依然没有一个固定范式,但概括起来有下面四个特征: 没有多余的效果,例如投影.凹凸或渐变等 使用简洁风格的元素和图标 大胆丰富且明亮的配色风格 尽量减少装饰的极简设计 扁平化所追随的细节依然不变,然而这些“规范”开始松懈了.随着扁平化进化到2.0时

浅谈html语义化标签,Html5新增语义化标签

Html语义化标签,Html5新增语义化标签 自己在学习的期间,整理了下html关于语义化标签的一些知识,列的不是很全. 希望大家有新的见解可以给我留言,我会补充上去,谢谢大家 1.什么是语义化标签? 那么什么叫做语义化呢,说的通俗点就是:明白每个标签的用途(在什么情况下我可以使用这个标签才合理)比如, 网页上的文章的标题就可以用标题标签,网页上的各个栏目的栏目名称也可以使用标题标签. 文章中内容的段落就得放在段落标签中,在文章中有想强调的文本,就可以使用em标签表示强调等等. 2.为啥使用语义