当前位置: 首页 > news >正文

郑州餐饮网站建设公司百度网址提交入口

郑州餐饮网站建设公司,百度网址提交入口,宝塔搭建完wordpress,wordpress 搜索 插件this指向 普通函数:this 的指向由调用方式决定,可以是全局对象、调用该函数的对象,或者显式指定的对象。箭头函数:this 的指向在定义时确定,始终继承自外层函数作用域的 this,不会被调用方式影响。 var obj…

  this指向

  • 普通函数this 的指向由调用方式决定,可以是全局对象、调用该函数的对象,或者显式指定的对象。
  • 箭头函数this 的指向在定义时确定,始终继承自外层函数作用域的 this,不会被调用方式影响。
var obj = {print: function() {var test = () =>  {console.log("yupi", this);}test();},rap: {doRap:() =>  {console.log(this);}}
}
var copyPrint = obj.print;
copyPrint();
obj.print();
obj.rap.doRap();//直接在 obj.rap 对象中定义,并没有包裹在任何外层函数中,会继承全局作用域的 this

var obj = {name: "yupi",func: function() {var self = this;console.log(this.name);console.log(self.name);(function() {console.log(this.name);console.log(self.name);}());}
};
obj.func();
//输出
yupi
yupi
undefined
yupi
var num = 2;
function print() {console.log(this.num);
}var obj = {num: 4,test1: print,test2: function () {print();},
};
obj.test1();
obj.test2();
var foo = obj.test1;
foo();
//输出结果
4
2
2
function test(num){this.value = num;return this;
}
var value = test(5);
var obj = test(6);console.log(value.value);
console.log(obj.value);
//输出结果
**undefined**6
function test(value) {this.num = value;
}var obj1 = {test: test,
};
obj1.test(1);
console.log(obj1.num);var obj2 = {};
obj1.test.call(obj2, 2);
console.log(obj2.num);var foo = new obj1.test(3);
console.log(obj1.num);
console.log(foo.num);//输出结果
1213function test(value){this.num = value;
}var obj1 = {};
var testBind = test.bind(obj1);
testBind(1);
console.log(obj1.num);var foo = new testBind(2);
console.log(obj1.num);
console.log(foo.num);
//输出结果
1
1
2

 优先级:new 绑定>显示绑定( apply/call/bind )>

               隐式绑定( obj.foo())>默认绑定( 独立函数调用 )

立即执行函数表达式 IIFE

什么是 IIFE(立即执行函数表达式)?

IIFE(Immediately Invoked Function Expression)是一种 JavaScript 编程模式,它使一个函数在定义时立即执行。IIFE 的格式通常如下所示:

  • (function() { // 函数体 })();
  • (() => { // 函数体 })();

立即执行函数的执行机制

  • 在上面的代码中,IIFE 是通过 (function() {...})() 形式定义的。它是一个 函数表达式并且在定义后立即执行。也就是说,IIFE 在 初始化时 执行一次,并且其作用域内的代码也只会执行一次。

对应到您的代码中的 IIFE

在您提供的代码中,IIFE 部分是:

window.num = 2;
var obj = {num: 4,test: (function(){console.log(this);this.num *= 6;return function(){console.log(this);this.num *= 8;}})()
}
var test = obj.test;
test();
obj.test();
console.log(obj.num);
console.log(window.num);//输出结果
Window 对象
Window 对象
{num: 4, test: ƒ} // obj 对象
32
96
  • 这段代码中的 IIFE 会在 定义 test 属性时立即执行console.log(this) 在 IIFE 执行时打印的是 全局对象 window,然后 this.num *= 6; 会修改 window.num 的值。
  • 该 IIFE 返回了一个匿名函数,这个匿名函数会赋值给 obj.test

总结:IIFE 是立即执行的,因此它的代码块只会执行一次,并且返回的函数会被赋给 obj.test。这个返回的函数之后会被调用,但 IIFE 本身只在定义时执行一次。

解释执行顺序

  1. 在执行到 var obj = { ... } 这一行时,IIFE 被立即执行:

    • console.log(this) 打印 window 对象。
    • this.num *= 6 修改了 window.num2 * 6 = 12)。
    • 然后,IIFE 返回一个匿名函数,该匿名函数被赋给 obj.test
  2. 之后,obj.test 就是 IIFE 返回的匿名函数,该函数在后面的调用中会执行:

    • 第一次调用 test() 时,this 指向 windowwindow.num 被修改为 96
    • 第二次调用 obj.test() 时,this 指向 objobj.num 被修改为 32

IIFE 的核心特性:

  • 只执行一次:IIFE 在定义时立即执行,并且它的作用域只会被创建一次。
  • 返回值:IIFE 可以返回任何值,在您的代码中,它返回了一个函数,这个函数被赋值给 obj.test
  • 默认this指向windows(非严格模式) 

⭐⭐进阶题

var length = 10;
function func() {console.log(this.length);
}var obj = {length: 5,test: function(func) {console.log(this.length)//5func();//相当于window.func(),被window对象调用this指向window对象//func.call(this)//这样修改this指向,this就是指向objarguments[0]();//类似于func(),但是调用方式不同,this不同,含义大不相同,这个可以看作函数被arguments对象调用,而arguments对象本省就有length属性,即为参数的个数,所以this.length输出为2(参数个数)}
};
obj.test(func, 1);

 输出为

  • 10
  • 2

刚看到一道JS面试题,关于this指向的问题

var length = 10;
function func() {
  console.log(this.length);
}

var obj = {
  length: 5,
  test: function(func) {
    console.log(this.length)//5
    func();//相当于window.func(),被window对象调用this指向window对象
    //func.call(this)//修改this指向,this就是指向obj
    arguments[0]();//类似于func(),但是调用方式不同,this不同,含义大不相同,这个可以看作函数被arguments对象调用,而arguments对象本身就有length属性,即为参数的个数,所以this.length输出为2(参数个数)
  }
};
obj.test(func, 1);
 

⭐扩展知识:词法作用域

在 JavaScript 中,**词法作用域(Lexical Scope)**是指函数的作用域(即变量的可访问范围)是根据函数定义的位置来确定的而不是根据函数调用的位置来决定的。这意味着 JavaScript 中的作用域链是静态的,它依赖于代码在编写时的结构。

1. 什么是词法作用域?

词法作用域(也叫静态作用域)是指一个函数在定义时决定了它能访问哪些变量。即,函数访问外部变量的规则与它们的定义位置有关,而与函数如何被调用时的调用位置无关。

- **函数的作用域链**是由函数定义时外部的作用域链决定的,而不是调用时的执行环境。

 2. 如何理解词法作用域?

- 在 JavaScript 中,**变量的作用域**决定了变量的可访问范围。
- **函数的作用域**决定了函数内部可以访问哪些变量。

当你定义一个函数时,它会记住外部的作用域链,并且无论何时调用它,函数总是能访问到它定义时可访问的那些变量。

举个简单的例子:

function outer() {var outerVar = 'I am from outer!';function inner() {console.log(outerVar); // 访问外部函数的变量}inner(); // 调用 inner 函数
}outer(); // 输出 "I am from outer!"

在这个例子中:
- `inner` 函数定义在 `outer` 函数内部,因此它可以访问 `outer` 函数中定义的变量 `outerVar`。
- 这就是**词法作用域**,因为 `inner` 函数的作用域是由它定义的位置(即在 `outer` 函数内部)决定的,而不是由它调用的位置决定的。

 3. 词法作用域与 `this`

在 JavaScript 中,`this` 的指向和作用域是两个不同的概念。虽然 `this` 和作用域链都与上下文相关,但它们的行为方式不同。理解词法作用域有助于理解 **箭头函数** 中 `this` 的行为。

普通函数和箭头函数的区别

- **普通函数**中的 `this` 是根据**调用时的上下文**来确定的。
- **箭头函数**中的 `this` 是在**定义时继承**外层作用域的 `this`,这就是箭头函数不同于普通函数的一大特点。

4. 箭头函数中的 `this`

箭头函数中的 `this` 绑定规则与普通函数不同。普通函数的 `this` 是动态绑定的,而箭头函数的 `this` 是静态的,指向定义时外层的 `this`。

例子:

function Outer() {this.name = 'Outer';// 普通函数this.printName = function() {console.log(this.name); // this 指向调用它的对象};// 箭头函数this.arrowPrintName = () => {console.log(this.name); // this 会继承自 Outer 函数的 this};
}var obj = new Outer();
obj.printName();      // 输出 'Outer',this 指向 obj
obj.arrowPrintName(); // 输出 'Outer',this 仍然指向 Outer 函数的 this

在上面的例子中:
- `printName` 是普通函数,它的 `this` 会根据调用时的上下文来确定。
- `arrowPrintName` 是箭头函数,它的 `this` 会继承外层 `Outer` 函数中的 `this`,即指向创建它时的 `this`,而不受 `obj` 的影响。

5. 作用域链

每个 JavaScript 函数都会创建一个作用域链,用于查找变量。当一个函数内部访问变量时,JavaScript 会沿着作用域链查找这个变量。如果函数内部没有定义某个变量,JavaScript 会查找函数外部的作用域,直到全局作用域为止

- **作用域链**是由多个作用域组成的,最里层的是当前函数的作用域,外层是它的外部作用域,一直到全局作用域。```javascript

function outer() {var outerVar = 'outer';function inner() {var innerVar = 'inner';console.log(outerVar); // 在内层函数中访问外层函数的变量}inner();
}outer(); // 输出 'outer'

在上面的例子中:
- `inner` 函数在 `outer` 函数内部定义,它访问了外层的 `outerVar`。这是因为 `inner` 函数的作用域链包含了 `outer` 函数的作用域。

6. 词法作用域和闭包

https://gisjing.blog.csdn.net/article/details/143593869?spm=1001.2014.3001.5502&ydreferer=aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzU1MDQ5NjU1P3R5cGU9YmxvZw%3D%3D

闭包是指函数能够"记住"并访问它定义时的作用域,即使这个函数在定义时的作用域已经执行完毕。`

function outer() {var outerVar = 'outer';function inner() {console.log(outerVar); // 访问 outer 的变量}return inner;
}var closure = outer(); // 返回 inner 函数
closure(); // 输出 'outer'

在这个例子中,`inner` 函数是一个闭包,因为它记住了定义时的作用域(即 `outer` 函数的作用域),即使在外部调用时,`outerVar` 仍然是可以访问的。

7. 词法作用域与变量提升

JavaScript 中的**变量提升**(hoisting)指的是在执行代码之前,所有的 `var` 声明会被提升到作用域的顶部,但它们的赋值并不会被提升。```javascript

function example() {console.log(myVar); // undefined,因为声明被提升了,但赋值在后面var myVar = 10;
}example();

在这个例子中,`myVar` 的声明被提升了,但是它的值 `10` 是在执行到那行代码时才赋值的。所以输出是 `undefined`,而不是 `10`。

♥8. 总结

- **词法作用域**决定了变量和函数的可访问范围,它是由函数的定义位置而不是调用位置来确定的。
- **作用域链**:函数查找变量时,会沿着作用域链从内到外查找,直到全局作用域。
- **箭头函数的 `this`**:箭头函数的 `this` 不是根据调用方式决定的,而是继承自它定义时的外层作用域。
- **闭包**:函数可以记住并访问它定义时的作用域,即使外层函数已经执行完毕。

原型链

Javascript原型链-CSDN博客

  • boy.prototype->undefined
  • null.__proto__->TypeError

⭐⭐⭐JS中new关键字实例化对象,具体做了什么⭐⭐⭐

  1. 创建一个空对象

    • new关键字被调用时,JavaScript引擎首先会创建一个空白的对象。这个对象没有任何属性和方法,但它会继承自构造函数的prototype属性所向的原型对指象。
  2. 设置原型链

    • 接下来,JavaScript引擎会将新创建的对象的内部原型(__proto__)设置为构造函数的prototype属性。这一步是原型链继承的关键,它允许新对象访问构造函数原型中定义的方法和属性。
  3. 绑定this并执行构造函数

    • 然后,JavaScript引擎会将构造函数作为普通函数调用,但此时this关键字的值会被设置为新创建的对象。这意味着在构造函数内部,你可以通过this来引用新对象,并向其添加属性和方法。
    • 构造函数中的代码会执行,可能会初始化对象的属性、调用其他方法等。
  4. 返回新对象

    • 最后,如果构造函数没有显式地返回一个对象(即返回的不是一个非原始值),那么new表达式会默认返回新创建的对象。如果构造函数返回了一个对象,那么new表达式会返回这个对象,而不是新创建的那个空对象。需要注意的是,这种情况下,原型链的链接会失去作用,因为返回的对象与构造函数的原型没有直接联系。
  • 创建一个新的空对象,并将这个对象的原型设置为函数的 prototype 属性。
  • 绑定函数内部的 this 到这个新对象,即在函数内 this 指向新创建的对象
  • 执行函数,将函数内部的代码与新对象的作用域绑定。
  • 返回值处理:如果函数返回一个非 null 的对象,则 new 表达式会返回这个对象;否则,它会返回创建的对象。

实现继承的几种方式

1.原型链继承

子类prototype指向父类实例。缺:所有实例共享父类属性,修改子类实例会影响到所有实例 

function Coder() {this.type = 'Coder';
}Coder.prototype.rap = function () {console.log('yo yo yo');
};function Yupi(name) {this.name = name;this.age = 18;
}// 原型链继承
Yupi.prototype = new Coder();
Yupi.prototype.constructor = Yupi;// 测试
const yupi = new Yupi('Yupi');
console.log(yupi.type); // 输出: Coder
yupi.rap(); // 输出: yo yo yo
2.构造函数

子类构造函数调用父类构造函数实现,可继承父类属性,但不能继承父类原型方法

function Coder() {this.type = 'Coder';
}Coder.prototype.rap = function () {console.log('yo yo yo');
};function Yupi(name) {Coder.call(this); // 调用父类构造函数this.name = name;this.age = 18;
}// 测试
const yupi = new Yupi('Yupi');
console.log(yupi.type); // 输出: Coder
// yupi.rap(); // 这行代码会报错,因为构造函数继承无法继承原型链上的方法
3.组合继承(组合1和2)

开销较大,两次调用父类构造函数

function Coder() {this.type = 'Coder';
}Coder.prototype.rap = function () {console.log('yo yo yo');
};function Yupi(name) {Coder.call(this); // 调用父类构造函数this.name = name;this.age = 18;
}// 组合继承
Yupi.prototype = new Coder();
Yupi.prototype.constructor = Yupi;// 测试
const yupi = new Yupi('Yupi');
console.log(yupi.type); // 输出: Coder
yupi.rap(); // 输出: yo yo yo
4.寄生组合(推荐⭐)

避免组合继承两次调用父类构造函数

function Coder() {this.type = 'Coder';
}Coder.prototype.rap = function () {console.log('yo yo yo');
};function Yupi(name) {Coder.call(this); // 调用父类构造函数this.name = name;this.age = 18;
}// 寄生组合继承
Yupi.prototype = Object.create(Coder.prototype);
Yupi.prototype.constructor = Yupi;// 测试
const yupi = new Yupi('Yupi');
console.log(yupi.type); // 输出: Coder
yupi.rap(); // 输出: yo yo yo
5.ES6 class语法
class Coder {constructor() {this.type = 'Coder';}rap() {console.log('yo yo yo');}
}class Yupi extends Coder {constructor(name) {super(); // 调用父类构造函数this.name = name;this.age = 18;}
}// 测试
const yupi = new Yupi('Yupi');
console.log(yupi.type); // 输出: Coder
yupi.rap(); // 输出: yo yo yo

**基础补充**

function Father(){this.a=11;this.b=[1,2,this.a];this.print=function(){console.log(this.a,this.b,typeof(this.b[2]));}
}
const father=new Father();
father.print();
father.a=13;
father.print();
//输出
//11 [1,2,11] number
//13 [1,2,11] number
//b中的this.a是复制a的值,类型为原始类型

自己身上没有才去原型链上找

function Obj1() {}
function Obj2(value) {this.value = value;
}
function Obj3(value) {if (value) {this.value = value;}
}Obj1.prototype.value = 1;
Obj2.prototype.value = 1;
Obj3.prototype.value = 1;console.log(new Obj1().value);
console.log(new Obj2().value);
console.log(new Obj3(666).value);1
undefined
666

函数原型与对象原型 

var FuncObj = function () {};
Object.prototype.foo = function () {console.log('foo');
};
Function.prototype.bar = function () {console.log('bar');
};
FuncObj.foo();
FuncObj.bar();var f = new FuncObj();
f.foo();
f.bar();//输出结果
foo
bar
foo
TypeError: f.bar is not a function

⭐⭐**进阶题1**⭐⭐

前端分享一经典有难度易错的Javascript题目

function Father() {this.a = 1;this.b = [1, 2, this.a];this.c = { field: 5 };this.print = function () {console.log(this.a, this.b, this.c.field);};
}function Son() {this.a = 2;this.update = function () {this.b.push(this.a);this.a = this.b.length;this.c.field = this.a++;};
}Son.prototype = new Father();
var father = new Father();
var son1 = new Son();
var son2 = new Son();
son1.a = 11;
son2.a = 12;
father.print();
son1.print();
son2.print();
son1.update();
son2.update();
father.print();
son1.print();
son2.print();
1 [ 1, 2, 1 ] 5
11 [ 1, 2, 1 ] 5
12 [ 1, 2, 1 ] 5
1 [ 1, 2, 1 ] 5
5 [ 1, 2, 1, 11, 12 ] 5
6 [ 1, 2, 1, 11, 12 ] 5

代码执行过程及结果分析

  1. 定义 FatherSon 构造函数

    • Father 构造函数初始化属性 a(值为1),b(值为 [1, 2, this.a],即 [1, 2, 1]),c(对象 { field: 5 }),以及 print 方法。
    • Son 构造函数初始化属性 a(值为2)和 update 方法。Son.prototype = new Father(); 使得 Son 的实例对象能够继承 Father 中定义的 abcprint
  2. 实例化对象

    • var father = new Father(); 创建了一个 Father 的实例 father,其属性值为 a = 1b = [1, 2, 1]c = { field: 5 }
    • var son1 = new Son();var son2 = new Son(); 创建了两个 Son 的实例 son1son2。由于继承了 Father,它们各自拥有独立的 a 值(由 Son 构造函数初始化为2)和独立的 bc 的引用(通过继承 Father 的实例化对象)。因此,son1son2 的初始属性为 a = 2b = [1, 2, 1]c = { field: 5 }
  3. 修改属性

    • son1.a = 11;son1a 属性设置为11。
    • son2.a = 12;son2a 属性设置为12。
  4. 调用 print 方法

    • father.print(); 输出 father 的属性:a = 1b = [1, 2, 1]c.field = 5。结果为:1 [1, 2, 1] 5
    • son1.print(); 输出 son1 的属性:a = 11b = [1, 2, 1]c.field = 5。结果为:11 [1, 2, 1] 5
    • son2.print(); 输出 son2 的属性:a = 12b = [1, 2, 1]c.field = 5。结果为:12 [1, 2, 1] 5
  5. 调用 update 方法

    • son1.update(); 执行以下操作:

      • this.b.push(this.a);son1.a(即11)添加到 b 中,因此 son1.b 变为 [1, 2, 1, 11]
      • this.a = this.b.length;son1.a 更新为 b 的长度(4)。
      • this.c.field = this.a++;son1.c.field 设置为 a(即4),然后自增 a 为5。
      • 更新后,son1.a = 5son1.b = [1, 2, 1, 11]son1.c = { field: 4 }
    • son2.update(); 执行以下操作:

      • this.b.push(this.a);son2.a(即12)添加到 b 中,因此 son2.b 变为 [1, 2, 1, 11, 12]
      • this.a = this.b.length;son2.a 更新为 b 的长度(5)。
      • this.c.field = this.a++;son2.c.field 设置为 a(即5),然后自增 a 为6。
      • 更新后,son2.a = 6son2.b = [1, 2, 1, 11, 12]son2.c = { field: 5 }
  6. 再次调用 print 方法

    • father.print(); 仍然输出原始的 father 属性:a = 1b = [1, 2, 1]c.field = 5。结果为:1 [1, 2, 1] 5
    • son1.print(); 输出更新后的 son1 属性:a = 5b = [1, 2, 1, 11, 12]c.field = 5。结果为:5 [1, 2, 1, 11, 12] 5
    • son2.print(); 输出更新后的 son2 属性:a = 6b = [1, 2, 1, 11, 12]c.field = 5。结果为:6 [1, 2, 1, 11, 12] 5

在这个示例中,son1son2 实例共享了 Father 原型中的 bc 引用,因此 update 方法对 b 数组的修改会影响到所有 Son 实例

⭐⭐**进阶题2**⭐⭐

function FuncObj() {print = function () {console.log(1);};//重新给print变量赋值return this;//返回了this
}FuncObj.print = function () {console.log(2);
};FuncObj.prototype.print = function () {console.log(3);
};var print = function () {console.log(4);
};function print() {console.log(5);
}FuncObj.print();
print();
FuncObj().print();//相当于调用windows.print()
print();
new FuncObj.print();//调用静态方法FuncObj.print()
new FuncObj().print();//构造方法FuncObj()实例化对象,对象的print()没找到->原型上找
new new FuncObj().print();//构造方法FuncObj()实例化对象找原型上print(),再调用此方法-》仍输出3
//输出结果
2
4(变量提升,var与函数声明同名时,var声明会在提升阶段覆盖函数声明)
1
1
2
3
3
调用和输出分析
1. FuncObj.print();
  • 这是调用 FuncObj 的静态方法 print
  • 输出:2
2. print();
  • 此时 print 是定义为 var print = function () { console.log(4); }
  • 输出:4
3. FuncObj().print();
  • 调用 FuncObj(),由于 FuncObj 返回 this(即全局对象 window),它会将 print 重新定义为 function () { console.log(1); },覆盖了全局的 print
  • 然后调用 print(),即 function () { console.log(1); }
  • 输出:1
4. print();
  • 上一步中 print 被重新赋值为 function () { console.log(1); }
  • 输出:1
5. new FuncObj.print();
  • new FuncObj.print() 调用的是 FuncObj 的静态方法 print,而非实例化 FuncObjnew 操作符在此上下文中无意义,但会正常执行【简单来讲就是不涉及原型链和this使用】
  • 输出:2

为什么 new 在这里无意义

在这个过程中,new 仅仅用来调用 FuncObj.print,并没有创建 FuncObj 的实例。它的主要效果仅是创建一个与 FuncObj 无关的空对象,作为 FuncObj.printthis,并执行了 FuncObj.print 函数体。

  • new 在此无意义,因为 FuncObj.print 并不使用 this,返回的空对象也没有用。
  • 效果等同于 FuncObj.print(),唯一的区别是返回一个空对象,但对 FuncObj.print 的执行没有任何影响。
6. new FuncObj().print();
  • new FuncObj() 创建了一个 FuncObj 的实例,该实例继承了 FuncObj.prototype.print 方法。
  • 调用实例的 print 方法,即 FuncObj.prototype.print
  • 输出:3
7. new new FuncObj().print();
  • new FuncObj() 创建了一个 FuncObj 的实例,且 new FuncObj().print 返回 FuncObj.prototype.print 方法。
  • 最外层 new 调用 FuncObj.prototype.print 方法,仍然输出 3
  • 输出:3

http://www.qdjiajiao.com/news/4576.html

相关文章:

  • 网站建设线上线下双服务器seo关键词排行优化教程
  • 福州企业网站推广百度收录情况查询
  • 塑胶原料东莞网站建设技术支持怎么关键词优化网站
  • 网站推广应该注意什么引流app推广软件
  • 游戏私服发布网站怎么做网络seo是什么工作
  • 房产信息网站模板b站免费版入口
  • 做网站开发学什么语言好cpa推广接单平台
  • 怎样用网站模板做网站百度一下你就知道官页
  • 甘肃省铁路投资建设集团有限公司网站东莞seo靠谱
  • 大数据时代的智能营销seo短视频网页入口引流免费
  • 重庆有哪些做网站 小程序的网站推广方式组合
  • 设计网站的功能有哪些内容通州区网站快速排名方案
  • 服装网站建设物流配送系统渠道推广策略
  • 舟山网站建设一个新的app如何推广
  • 青岛做网站好的公司自贡网站seo
  • 唐山网站建设外包公司专门代写平台
  • yyf做的搞笑视频网站推广哪些app最挣钱
  • 云南通耀建设工程有限公司网站鸡西seo
  • 淘宝美工网站怎么做如何自建网站
  • 一般pr做视频过程那个网站有免费入驻的电商平台
  • 做任务免费得晋江币网站楚雄百度推广电话
  • 济南广运建设公司网站新媒体seo培训
  • 柳州城乡建设管理局网站环球军事网最新消息
  • 北京市网站设计百度快速排名软件
  • wordpress独立页面插件谷歌seo技巧
  • 江苏大汉建设实业集团网站微营销平台系统
  • 电商型网站建设价格海南网站制作公司
  • 网络科技有限公司网站建设策划书济南网站设计
  • 2014 网站建设网站怎么优化自己免费
  • wordpress memcache成都网站seo技巧