Call函数

  • Post author:
  • Post category:其他




Call函数


  • Function.prototype.call()

标题 内容
Call的定义 什么是Call函数?
Call的使用 如何使用Call函数?
Call的实现原理 如何实现Call函数?
Call的示例 Call函数实现继承等



Call的定义


  • call()

    方法使用一个

    指定的

    this





    单独给出的一个

    或者

    多个参数



    调用一个函数

function People(name, age) {
  this.name = name;
  this.age = age;
}

function Person(name, age) {
  People.call(this, name, age);
  this.tall = '185';
}


var person = new Person('jackdan', 25);

console.log(person) // Object { name: "jackdan", age: 25, tall: "185" }
console.log(person.name) // "jackdan"



call的语法

/**
 * @desciption Function.prototype.call()
 * 
*/
function.call(thisArg, arg1, arg2, arg3, ...)



参数说明


  • thisArg

    : 可选的。在

    function

    函数运行时使用的

    this

    值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null或者undefined会自动替换为指向全局变量,原始值会被包装。

  • 详细解释(理解记忆): 在

    ECMAScript 5的严格模式

    中,

    call()



    apply()



    第一个实参

    也就是

    thisArg

    都会变为


    this

    的值

    ,哪怕传入的实参是

    原始值

    甚至是

    null

    或者

    undefined

    。在

    ECMAScript 3



    非严格模式

    中,传入的

    null



    undefined

    都会被

    全局对象代替

    ,而

    其他原始值则会被相应的包装对象(

    wrapper object

    )所代替

// 非严格模式
var name = 'jackdan';

function sayName() {
  console.log(this); // Window
  console.log('My Name is %s', this.name)
}

sayName.call();
  • 严格模式:
// 严格模式
'use strict'

var name = 'jackdan';

function sayName() {
  console.log(this); // undefined
  console.log('My Name is %s', this.name); // Uncaught TypeError: Cannot read property 'name' of undefined
}

sayName.call();

  • arg1, arg2, agr3, ...

    : 指定的参数列表。



返回值


  • 使用调用者

    提供的

    this

    值和

    参数调用该函数的返回值

    。若该方法没有返回值,则返回

    undefined



描述


  • call()

    允许为

    不同的对象分配



    调用

    属于一个对象的

    函数/方法


  • call()

    提供新的this值给当前调用的函数/方法。你可以使用

    call

    来实现继承: 写一个方法,然后让另外一个

    新的对象来继承它

    (而不是在新对象中再写一次这个方法)
function People(name, age) {
  this.name = name;
  this.age = age;
}

function PersonJack(name, age) {
  People.call(this, name, age);
  this.tall = 185
}

function PersonRose(name, age) {
  People.call(this, name, age);
  this.tall = 165;
}

var jackdan = new PersonJack('jackdan', 26);
var rose = new PersonRose('rose', 24);
console.log(jackdan); // PersonJack {name: "jackdan", age: 26, tall: 185}
console.log(rose); // PersonRose {name: "rose", age: 24, tall: 165}



Call的实现


  • call()

    方法在使用一个指定的

    this

    值和若干个指定的参数值的前提下调用某个函数或方法。
var personObj = {
  name: 'jackdan'
}

var sayName = function() {
  console.log(this.name)
}

sayName.call(personObj); // jackdan
  • 等价于
var personObj = {
  name: 'jackdan',
  sayName: function() {
    console.log(this.name);
  }
}

personObj.sayName(); // jackdan

// 1. 将函数设为对象的属性
// 2. 执行该函数
// 3. 删除该函数

personObj.fn = personObj.sayName;

personObj.fn(); // jackdan

delete personObj.fn(); // jackdan

  • Function.prototype.myCall

    实现
Function.prototype.myCall = function(context) {
  context.fn = this;
  context.fn();
  delete context.fn();
}

var personObj = {
  name: 'jackdan'
}

var sayName = function() {
  console.log(this.name);
}

sayName.myCall(personObj);

  • Function.prototype.myCall

    带参数的实现
var personObj = {
  tall: 185
}

var sayName = function(name, age) {
  console.log(name);
  console.log(age);
  console.log(this.tall);
}

sayName.call(personObj, 'jackdan', 26); // jackdan 26 185
Function.prototype.myCall = function(context) {
  context = Object(context) || window;
  context.fn = this;

  var args = [];

  for(var i = 0, len = arguments.length; i < len; i++) {
    args.push('arguments[' + i + ']');
  }

  var result = eval('context.fn(' + args + ')');
  delete context.fn;
  return result;
}

var personObj = {
  tall: 185
}

var sayName = function(name, age) {
  console.log(name);
  console.log(age);
  console.log(this.tall);
}

sayName.myCall(personObj, 'jackdan', 26);



示例



使用 call 方法调用父构造函数

  • 在一个子构造函数中,你可以通过调用

    父构造函数



    call

    方法来

    实现继承

    ,类似于

    Java

    中的写法。下例中,使用

    Food



    Toy


    构造函数

    创建的对象实例都会拥有在

    Product

    构造函数中添加的

    name

    属性和

    price

    属性,但

    category

    属性是在

    各自的构造函数

    中定义的。
function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
console.log(cheese); // Food {name: "feta", price: 5, category: "food"}
console.log(fun); // Toy {name: "robot", price: 40, category: "toy"}



使用 call 方法调用匿名函数

  • 在下例中的

    for

    循环体内,我们创建了一个

    匿名函数

    ,然后通过调用该函数的

    call

    方法,将每个数组元素作为指定的

    this

    值执行了那个匿名函数。这个匿名函数的主要目的是给每个数组元素对象添加一个

    sayName

    方法,这个

    sayName

    方法可以打印出各元素在数组中的

    正确索引号

    。当然,这里不是必须得让数组元素作为

    this

    值传入那个匿名函数(普通参数就可以),目的是为了演示

    call

    的用法。
var people = [
  { name: 'jackdan', age: 26 },
  { name: 'rose', age: 24 }
];

for (var i = 0; i < people.length; i++) {
  (function(i) {
    this.sayName = function() {
      console.log('#' + i + ' ' + this.name + ': ' + this.age);
    }
    this.sayName();
  }).call(people[i], i);
}

// #0 jackdan: 26
// #1 rose: 24



使用 call 方法调用函数并且指定上下文的 ‘this’

  • 在下面的例子中,当调用

    sayName

    方法的时候,该方法的

    this

    值会绑定到

    obj

    对象。
function sayName() {
  var reply = [this.person, 'typically sleep between', this.sleepDuration].join(' ');
  console.log(reply);
}

var obj = {
  person: 'jackdan', sleepDuration: '8 and 10 hours'
};

sayName.call(obj); // jackdan typically sleep between 8 and 10 hours



使用 call 方法调用函数并且不指定第一个参数(argument)

  • 在下面的例子中,我们调用了

    sayName

    方法,但并没有传递它的

    第一个参数

    。如果没有

    传递第一个参数



    this

    的值将会被绑定为

    全局对象

// 非严格模式
var name = 'jackdan';

function sayName() {
  console.log(this); // Window
  console.log('My Name is %s', this.name)
}

sayName.call();
  • 严格模式: 如果没有传递第一个参数,

    this

    的值将会是undefined。

  • 建议

    : 还是需要在严格模式下去编写程序,避免

    全局对象带来作用域的污染

// 严格模式
'use strict'

var name = 'jackdan';

function sayName() {
  console.log(this); // undefined
  console.log('My Name is %s', this.name); // Uncaught TypeError: Cannot read property 'name' of undefined
}

sayName.call();

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call



版权声明:本文为XXJ19950917原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。