Seasons123 / blog-FE

web前端相关issue is my blog :lollipop:
2 stars 0 forks source link

《Object-Oriented JavaScript》—— 4.2.3 Function #14

Open Seasons123 opened 7 years ago

Seasons123 commented 7 years ago

4.2.3 Function

函数是一种特殊的数据类型,它实际上是一种对象。

4.2.3.3 call( )和apply( )

1.在JavaScript中,每个函数都有call()和apply()两个方法。 这两个方法的两个功能:

(1)用他们来触发函数,并指定相关的调用参数。
(2)他可以让一个对象去“借用“另一个对象的方法,并为已所用。这也是非常简单而实用的代码重用。

2.通过一个例子来讲解call (1)定义一个some_obj对象,该对象有一个say()方法:

var some_obj={
  name: 'peichunyan',
  say: function(who){
     return 'Haya' + who + ', I am ' + this.name;
  }
};

这样,就可以调用该对象的say( )方法了,并在其中使用this.name来访问其name属性了: some_obj.say( 'Kitty'); //输出:Haya Kitty, I am peichunyan (2)下面,我们再创建一个my_obj对象,它只有一个name属性: var my_obj={ name: 'LiYundi'}; (3)对于my_obj,也想拥有和some_obj的say( )方法相同功能的方法,因此,我们希望将该方法当做my_obj自身的方法来调用(没必要自己再重复实现一遍)。在这样情况下,我们就可以试试say( )函数中的对象方法call( ):

some_obj.say.call(my_obj, 'Yanglan');
//输出: "Haya Yanglan, I am LiYundi "

(4)解释:由于我们在调用say( )函数的对象方法call时传递了两个参数:对象my_obj和字符串"Yanglan”.这样一来,当say( )被调用时,其中的this就被自动设置成了my_obj对象的引用。因此我们看到,this.name返回的不再是“peichunyan”,而是“LiYundi”了。 (5)如果我们调用call方法时,需要传递更多的参数,可以在后面依次加入它们: some_obj.someMethod.call(my_obj, 'a', 'b', 'c');

  1. apply( ) apply( )的工作方式与call( )基本相同,唯一的不同之处在于参数的传递形式这里目标函数所需要的参数都是通过一个数组来传递。所以,下面两行代码的作用是等效的:
    some_obj.someMethod.call(my_obj, 'a', 'b', 'c');
    some_obj.someMethod.apply(my_obj, ['a', 'b', 'c']);

    所以,对于之前的示例,也可以这样写:

    some_obj.say.apply(my_obj, [ 'Yanglan']);
    //输出: "Haya Yanglan, I am LiYundi "

4.2.3.4重新认识arguments对象

1.可以在一个函数中通过arguments来访问传递给该函数所需的全部参数。栗子:

function f( ){
   return arguments;
}

f(1,2,3);   //[1,2,3]

2.尽管arguments看上去像是一个数组,但它实际上是一个类似数组的对象。它和数组相似是因为其中也包含了索引元素length属性。但相似之处也就到此为止了,因为arguments不提供一些像sort()、slice()这样的数组方法。

  1. 但我们可以把arguments转换成数组,这样就可以对它使用各种各样的数组方法了。 例子:
    
    function f( ){
    var  args = [].slice.call( arguments);
    return args.reverse( );
    }

f(1,2,3,4); //[4,3,2,1]


这里的做法是:新建一个空数组,再使用它的slice属性。也可以用Array.prototype.slice来调用同一个函数。
Seasons123 commented 7 years ago

4.2.3.5 推断对象类型

(1)问题:既然数组的typeof返回值也是“object”,那么要如何区分对象和数组呢? (2)答案:使用Object对象的toString()方法。这个方法会返回所创建对象的内部类名。 (3)例:

Object.prototype.toString.call( { } );        // [object Object]
Object.prototype.toString.call( [ ] );        // [object Array]

在这里,toString()方法必须要来自于Object构造器的prototype属性。直接调用Array的toString()方法是不行的,因为在Array对象里,这个方法已经出于其它目的被重写了。 [1, 2, 3].toString( );

Seasons123 commented 6 years ago

【补充】js有名函数表达式 2

这里面的表达式是有名函数表达式,不规范,g()只能在函数内部访问。 typeof就会Error。

Seasons123 commented 6 years ago

3.2预定义函数

3.2.5 URI(统一资源标识符)的编码与反编码 p69

encodeURI(), decodeURI()它们都是Global对象的方法。 encodeURI()通过将某些字符的每个实例替换代表字符的UTF-8编码的一个或多个转义字符来编码URI。规则如下:

不会编码保留字符 ; , / ? : @ & = + $
不会编码未转义的字符:字母,十进制数字以及- _ . ! ~ * ' ( )
不会编码Number sign:#
需要注意:由于'&', '+', '='未被编码,在GET和POST请求中被视为特殊字符,所以encodeURI不能形成适
当的 HTTP GET 和POST请求。因此,要使用encodeURIComponent()来编码部分字符。

encodeURIComponent()会将传入的部分字符串部分全部进行编码。它的编码规则如下:

未转义的字符:字母,十进制数字以及- _ . ! ~ * ' ( )
除了上面的字符,其他字符都会被编码。

decodeURI()作用和encodeURI()相反。 decodeURIComponent()作用和encodeURIComponent()相反